1 
2 /******************************************************************************
3 * MODULE     : wk_widget.cpp
4 * DESCRIPTION: Definition of abstract native widgets
5 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11 
12 #include "window.hpp"
13 #include "Widkit/wk_widget.hpp"
14 #include "Widkit/Event/basic_event.hpp"
15 #include "analyze.hpp"
16 #include "font.hpp"
17 
18 /******************************************************************************
19 * Widget construction and destruction
20 ******************************************************************************/
21 
22 extern int widget_count;
wk_widget_rep(array<wk_widget> a2,array<string> n2,gravity grav2)23 wk_widget_rep::wk_widget_rep (
24   array<wk_widget> a2, array<string> n2, gravity grav2):
25     win (NULL), ox (0), oy (0), w (0), h (0),
26     grav (grav2), a (a2), name (n2) { TM_DEBUG(widget_count++); }
27 
~wk_widget_rep()28 wk_widget_rep::~wk_widget_rep () { TM_DEBUG(widget_count--); }
29 
30 /******************************************************************************
31 * Computing lower left and upper right widget coordinates
32 ******************************************************************************/
33 
34 SI
get_dx(gravity grav,SI w)35 get_dx (gravity grav, SI w) {
36   switch (grav) {
37   case north_west: case west: case south_west:
38     return 0;
39   case north: case center: case south:
40     return (w/(2*PIXEL))*PIXEL;
41   case north_east: case east: case south_east:
42     return w;
43   }
44   FAILED ("unknown gravity");
45   return 0;
46 }
47 
48 SI
get_dy(gravity grav,SI h)49 get_dy (gravity grav, SI h) {
50   switch (grav) {
51   case north_west: case north: case  north_east:
52     return 0;
53   case west: case center: case east:
54     return ((-h)/(2*PIXEL))*PIXEL;
55   case south_west: case south: case south_east:
56     return -h;
57   }
58   FAILED ("unknown gravity");
59   return 0;
60 }
61 
62 gravity
opposite(gravity grav)63 opposite (gravity grav) {
64   switch (grav) {
65   case north_west: return south_east;
66   case north     : return south;
67   case north_east: return south_west;
68   case west      : return east;
69   case center    : return center;
70   case east      : return west;
71   case south_west: return north_east;
72   case south     : return north;
73   case south_east: return north_west;
74   }
75   FAILED ("unknown gravity");
76   return center;
77 }
78 
79 SI
x1()80 wk_widget_rep::x1 () {
81   return ox- get_dx (grav, w);
82 }
83 
84 SI
y1()85 wk_widget_rep::y1 () {
86   return oy- get_dy (grav, h)- h;
87 }
88 
89 SI
x2()90 wk_widget_rep::x2 () {
91   return ox- get_dx (grav, w)+ w;
92 }
93 
94 SI
y2()95 wk_widget_rep::y2 () {
96   return oy- get_dy (grav, h);
97 }
98 
99 /******************************************************************************
100 * Finding and assigning children by name
101 ******************************************************************************/
102 
103 static string
get_first(string s)104 get_first (string s) {
105   int i;
106   for (i=0; i<N(s); i++)
107     if (s[i] == '|') return s (0, i);
108   return s;
109 }
110 
111 wk_widget
operator [](string s)112 wk_widget::operator [] (string s) {
113   string l= get_first (s);
114   wk_widget w;
115   (*this) << get_widget (l, w);
116   if (l==s) return w;
117   else return w [s (N(l)+1, N(s))];
118 }
119 
120 /******************************************************************************
121 * Other routines
122 ******************************************************************************/
123 
124 bool
attached()125 wk_widget_rep::attached () {
126   return win != NULL;
127 }
128 
129 bool
is_window_widget()130 wk_widget_rep::is_window_widget () {
131   return false;
132 }
133 
134 void
wk_error(string message)135 wk_widget_rep::wk_error (string message) {
136   widkit_error << "------------------------------------------------------------------------------\n";
137   widkit_error << wk_widget (this);
138   widkit_error << "------------------------------------------------------------------------------\n";
139   widkit_error << message << "\n";
140 }
141 
142 wk_widget
operator <<(wk_widget w,event ev)143 operator << (wk_widget w, event ev) {
144   if (!w->handle (ev))
145     widkit_warning << ((tree) ev) << " cannot be handled by\n" << w << "\n";
146   return w;
147 }
148 
149 static void
print_tree(tm_ostream & out,tree t,int tab)150 print_tree (tm_ostream& out, tree t, int tab) {
151   int i;
152   for (i=0; i<tab; i++) out << "| ";
153   if (is_atomic (t)) out << as_string (t) << "\n";
154   else {
155     out << as_string (t[0]) << "\n";
156     for (i=1; i<N(t); i++) print_tree (out, t[i], tab+1);
157   }
158 }
159 
160 tm_ostream&
print(tm_ostream & out)161 wk_widget_rep::print (tm_ostream& out) {
162   print_tree (out, operator tree (), 0);
163   return out;
164 }
165 
166 tm_ostream&
operator <<(tm_ostream & out,wk_widget w)167 operator << (tm_ostream& out, wk_widget w) {
168   print_tree (out, (tree) w, 0);
169   return out;
170 }
171 
172 /******************************************************************************
173 * Pointer grabbing
174 ******************************************************************************/
175 
176 void
wk_grab_pointer(wk_widget w)177 wk_grab_pointer (wk_widget w) {
178   ASSERT (!is_nil (w) && w->win != NULL, "widget should be attached");
179   w->win->set_mouse_grab (abstract (w), true);
180 }
181 
182 void
wk_ungrab_pointer(wk_widget w)183 wk_ungrab_pointer (wk_widget w) {
184   ASSERT (!is_nil (w) && w->win != NULL, "widget should be attached");
185   w->win->set_mouse_grab (abstract (w), false);
186 }
187 
188 bool
wk_has_pointer_grab(wk_widget w)189 wk_has_pointer_grab (wk_widget w) {
190   return !is_nil (w) && w->win != NULL &&
191     w->win->get_mouse_grab (abstract (w));
192 }
193 
194 /******************************************************************************
195 * Length conversions
196 ******************************************************************************/
197 
198 #define SHRINK 3
199 
200 SI
decode_length(string width,wk_widget wid,int style)201 decode_length (string width, wk_widget wid, int style) {
202   SI ex, ey;
203   if (wid->win == NULL) gui_maximal_extents (ex, ey);
204   else wid->win->get_size (ex, ey);
205   if (ends (width, "w") && is_double (width (0, N(width) - 1))) {
206     double x= as_double (width (0, N(width) - 1));
207     return (SI) (x * ex);
208   }
209   else if (ends (width, "h") && is_double (width (0, N(width) - 1))) {
210     double y= as_double (width (0, N(width) - 1));
211     return (SI) (y * ey);
212   }
213   else if (ends (width, "em") && is_double (width (0, N(width) - 2))) {
214     font fn= get_default_styled_font (style);
215     double x= as_double (width (0, N(width) - 2));
216     return (SI) ((x * fn->wquad) / SHRINK);
217   }
218   else if (ends (width, "px") && is_double (width (0, N(width) - 2))) {
219     double x= as_double (width (0, N(width) - 2));
220     return (SI) (x * PIXEL);
221   }
222   else return ex;
223 }
224