Logo Search packages:      
Sourcecode: widelands version File versions  Download package

ui_panel.h

/*
 * Copyright (C) 2002-2004, 2006-2007 by the Widelands Development Team
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


#ifndef __S__PANEL_H
#define __S__PANEL_H

#include "error.h"
#include "geometry.h"
#include "types.h"
#include "ui_object.h"

#include <SDL_types.h>
#include <stdint.h> //  Because old version of SDL_types.h do not include this.

#include <string>

class RenderTarget;

#define BUTTON_EDGE_BRIGHT_FACTOR 60
#define MOUSE_OVER_BRIGHT_FACTOR 15

namespace UI {
/**
 * Panel is a basic rectangular UI element.
 * The outer rectangle is defined by (_x, _y, _w, _h) and encloses the entire panel,
 * including both border and inner area/rectangle.
 * The inner rectangle is the outer rectangle minus the border sizes.
 * Child panel coordinates are always relative to the inner rectangle.
 */
00047 struct Panel : public Object {
      enum {
00049             pf_handle_mouse = 1, ///< receive mouse events
00050             pf_think = 2, ///< call think() function during run
00051             pf_top_on_click = 4, ///< bring panel on top when clicked inside it
00052             pf_die = 8, ///< this panel needs to die
00053             pf_child_die = 16, ///< a child needs to die
00054             pf_visible = 32, ///< render the panel
00055             pf_can_focus = 64, ///< can receive the keyboard focus
00056             pf_snap_windows_only_when_overlapping = 128, ///< children should snap only when overlapping the snap target
00057             pf_dock_windows_to_edges = 256, ///< children should snap to the edges of this panel
      };

      Panel
            (Panel * const nparent,
             const int nx, const int ny, const uint nw, const uint nh,
             const std::string & tooltip_text = std::string());
      virtual ~Panel();

      inline Panel *get_parent() const {return _parent;}

      void free_children();

      // Modal
      static const int dying_code = -1;
      int run();
      void end_modal(int code);

      virtual void start();
      virtual void end();

      // Geometry
      void set_size(const uint nw, const uint nh);
      void set_pos(const Point);
      virtual void move_inside_parent();

      inline int get_x() const {return _x;}
      inline int get_y() const {return _y;}
      inline int get_w() const {return _w;}
      inline int get_h() const {return _h;}

      virtual bool is_snap_target() const {return false;}
      ushort get_border_snap_distance() const {return _border_snap_distance;}
      void set_border_snap_distance(const uchar value) {_border_snap_distance = value;}
      uchar get_panel_snap_distance () const {return _panel_snap_distance;}
      void set_panel_snap_distance(const uchar value) {_panel_snap_distance = value;}
      bool get_snap_windows_only_when_overlapping() const {return _flags & pf_snap_windows_only_when_overlapping;}
      void set_snap_windows_only_when_overlapping(const bool on = true);
      bool get_dock_windows_to_edges() const {return _flags & pf_dock_windows_to_edges;}
      void set_dock_windows_to_edges(const bool on = true);
      void set_inner_size(uint nw, uint nh);
      void fit_inner(Panel* inner);
      void set_border(uint l, uint r, uint t, uint b);

      inline uint get_lborder() const {return _lborder;}
      inline uint get_rborder() const {return _rborder;}
      inline uint get_tborder() const {return _tborder;}
      inline uint get_bborder() const {return _bborder;}

      inline int get_inner_w() const {return _w-(_lborder+_rborder);}
      inline int get_inner_h() const {return _h-(_tborder+_bborder);}

      const Panel * get_next_sibling () const {return _next;}
      const Panel * get_prev_sibling () const {return _prev;}
      const Panel * get_first_child  () const {return _fchild;}
      const Panel * get_last_child   () const {return _lchild;}

      void move_to_top();

      // Drawing, visibility
      inline bool get_visible() const {return (_flags & pf_visible) ? true : false;}
      void set_visible(bool on);

      virtual void draw(RenderTarget* dst);
      virtual void draw_border(RenderTarget* dst);
      virtual void draw_overlay(RenderTarget & dst);
      void update(int x, int y, int w, int h);
      void update_inner(int x, int y, int w, int h);
      void set_cache(bool enable);

      // Events
      virtual void think();

      Point get_mouse_position() const throw();
      void set_mouse_pos(const Point);
      void center_mouse();

      virtual void handle_mousein(bool inside);
      virtual bool handle_mousepress  (const Uint8 btn, int x, int y);
      virtual bool handle_mouserelease(const Uint8 btn, int x, int y);
      virtual bool handle_mousemove
            (const Uint8 state, int x, int y, int xdiff, int ydiff);
      virtual bool handle_key(bool down, int code, char c);

      void set_handle_mouse(bool yes);
      inline bool get_handle_mouse() const {return (_flags & pf_handle_mouse) ? true : false;}
      void grab_mouse(bool grab);

      void set_can_focus(bool yes);
      inline bool get_can_focus() const {return (_flags & pf_can_focus) ? true : false;}
      inline bool has_focus() const {assert(get_can_focus()); return (_parent->_focus == this);}
   void focus();

      void set_think(bool yes);
      inline bool get_think() const {return (_flags & pf_think) ? true : false;}

      inline void set_top_on_click(bool on) {
            if (on) _flags |= pf_top_on_click;
            else _flags &= ~pf_top_on_click;
      }
      inline bool get_top_on_click() const {return (_flags & pf_top_on_click) ? true : false;}

protected:
      void die();

   bool keyboard_free() {return !(_focus);}

      void play_click();

private:
      void check_child_death();

      void do_draw(RenderTarget* dst);

      /**
       * Returns the child panel that receives mouse events at the given location.
       * Starts the search with child (which should usually be set to _fchild) and
       * returns the first match.
       */
      Panel * child_at_mouse_cursor(int mouse_x, int mouse_y, Panel * child);
      void do_mousein(bool inside);
      bool do_mousepress  (const Uint8 btn, int x, int y);
      bool do_mouserelease(const Uint8 btn, int x, int y);
      bool do_mousemove(const Uint8 state, int x, int y, int xdiff, int ydiff);
      bool do_key(bool down, int code, char c);

      Panel *_parent;
      Panel *_next, *_prev;
      Panel *_fchild, *_lchild; // first, last child
      Panel *_mousein; // child panel the mouse is in
      Panel *_focus; // keyboard focus

      uint _flags;
      uint _cache;
      bool _needdraw;

      int _x, _y;
      uint _w, _h;
      uint _lborder, _rborder, _tborder, _bborder;
      uchar _border_snap_distance, _panel_snap_distance;

      bool _running;
      int _retcode;

      char * _tooltip;

      void draw_tooltip(RenderTarget* dst, Panel *lowest);

public:
      void set_tooltip(const char * const);
      const char * tooltip() const throw () {return _tooltip;}


private:
      static Panel *ui_trackmouse(int *x, int *y);
      static void ui_mousepress  (const Uint8 button, int x, int y);
      static void ui_mouserelease(const Uint8 button, int x, int y);
      static void ui_mousemove
            (const Uint8 state, int x, int y, int xdiff, int ydiff);
      static void ui_key(bool down, int code, char c);

      static Panel *_modal;
      static Panel *_g_mousegrab;
      static Panel *_g_mousein;
      static uint s_default_cursor;
};

inline void Panel::set_snap_windows_only_when_overlapping(const bool on) {
      _flags &= ~pf_snap_windows_only_when_overlapping;
      if (on) _flags |= pf_snap_windows_only_when_overlapping;
}
inline void Panel::set_dock_windows_to_edges(const bool on) {
      _flags &= ~pf_dock_windows_to_edges;
      if (on) _flags |= pf_dock_windows_to_edges;
}
};

#endif

Generated by  Doxygen 1.6.0   Back to index