1 | <HTML> |
---|
2 | <HEAD> |
---|
3 | <TITLE>7 - Adding and Extending Widgets</TITLE> |
---|
4 | </HEAD> |
---|
5 | <BODY> |
---|
6 | <H1 ALIGN=RIGHT><A NAME=subclassing>7 - Adding and Extending Widgets</A></H1> |
---|
7 | This chapter describes how to add your own widgets or extend existing |
---|
8 | widgets in FLTK. |
---|
9 | <H2>Subclassing</H2> |
---|
10 | New widgets are created by <I>subclassing</I> an existing FLTK widget, |
---|
11 | typically <TT>Fl_Widget</TT> for controls and <TT>Fl_Group</TT> for |
---|
12 | composite widgets. |
---|
13 | <P>A control widget typically interacts with the user to receive and/or |
---|
14 | display a value of some sort. </P> |
---|
15 | <P>A composite widget widget holds a list of child widgets and handles moving, |
---|
16 | sizing, showing, or hiding them as needed. <TT>Fl_Group</TT> is the |
---|
17 | main composite widget widget class in FLTK, and all of the other composite widgets (<TT> |
---|
18 | Fl_Pack</TT>, <TT>Fl_Scroll</TT>, <TT>Fl_Tabs</TT>, <TT>Fl_Tile</TT>, |
---|
19 | and <TT>Fl_Window</TT>) are subclasses of it. </P> |
---|
20 | <P>You can also subclass other existing widgets to provide a different |
---|
21 | look or user-interface. For example, the button widgets are all |
---|
22 | subclasses of <TT>Fl_Button</TT> since they all interact with the user |
---|
23 | via a mouse button click. The only difference is the code that draws |
---|
24 | the face of the button. </P> |
---|
25 | <H2>Making a Subclass of Fl_Widget</H2> |
---|
26 | Your subclasses can directly descend from <TT>Fl_Widget</TT> or any |
---|
27 | subclass of <TT>Fl_Widget</TT>. <TT>Fl_Widget</TT> has only four |
---|
28 | virtual methods, and overriding some or all of these may be necessary. |
---|
29 | <H2>The Constructor</H2> |
---|
30 | The constructor should have the following arguments: |
---|
31 | <UL><PRE> |
---|
32 | MyClass(int x, int y, int w, int h, const char *label = 0); |
---|
33 | </PRE></UL> |
---|
34 | This will allow the class to be used in <A href="fluid.html#FLUID">FLUID</A> |
---|
35 | without problems. |
---|
36 | <P>The constructor must call the constructor for the base class and |
---|
37 | pass the same arguments: </P> |
---|
38 | <UL><PRE> |
---|
39 | MyClass::MyClass(int x, int y, int w, int h, const char *label) |
---|
40 | : Fl_Widget(x, y, w, h, label) { |
---|
41 | // do initialization stuff... |
---|
42 | } |
---|
43 | </PRE></UL> |
---|
44 | <TT>Fl_Widget</TT>'s protected constructor sets <TT>x()</TT>, <TT>y()</TT>, |
---|
45 | <TT>w()</TT>, <TT>h()</TT>, and <TT>label()</TT> to the passed values |
---|
46 | and initializes the other instance variables to: |
---|
47 | <UL><PRE> |
---|
48 | type(0); |
---|
49 | box(FL_NO_BOX); |
---|
50 | color(FL_BACKGROUND_COLOR); |
---|
51 | selection_color(FL_BACKGROUND_COLOR); |
---|
52 | labeltype(FL_NORMAL_LABEL); |
---|
53 | labelstyle(FL_NORMAL_STYLE); |
---|
54 | labelsize(FL_NORMAL_SIZE); |
---|
55 | labelcolor(FL_FOREGROUND_COLOR); |
---|
56 | align(FL_ALIGN_CENTER); |
---|
57 | callback(default_callback,0); |
---|
58 | flags(ACTIVE|VISIBLE); |
---|
59 | image(0); |
---|
60 | deimage(0); |
---|
61 | </PRE></UL> |
---|
62 | <H2>Protected Methods of Fl_Widget</H2> |
---|
63 | The following methods are provided for subclasses to use: |
---|
64 | <UL> |
---|
65 | <LI><A href=#clear_visible><TT>Fl_Widget::clear_visible</TT></A></LI> |
---|
66 | <LI><A href=#damage><TT>Fl_Widget::damage</TT></A></LI> |
---|
67 | <LI><A href=#draw_box><TT>Fl_Widget::draw_box</TT></A></LI> |
---|
68 | <LI><A href=#draw_focus><TT>Fl_Widget::draw_focus</TT></A></LI> |
---|
69 | <LI><A href=#draw_label><TT>Fl_Widget::draw_label</TT></A></LI> |
---|
70 | <LI><A href=#set_flag><TT>Fl_Widget::set_flag</TT></A></LI> |
---|
71 | <LI><A href=#set_visible><TT>Fl_Widget::set_visible</TT></A></LI> |
---|
72 | <LI><A href=#test_shortcut><TT>Fl_Widget::test_shortcut</TT></A></LI> |
---|
73 | <LI><A href=#type><TT>Fl_Widget::type</TT></A></LI> |
---|
74 | </UL> |
---|
75 | <H4><A name=damage>void Fl_Widget::damage(uchar mask) |
---|
76 | <BR> void Fl_Widget::damage(uchar mask, int x, int y, int w, int h) |
---|
77 | <BR> uchar Fl_Widget::damage()</A></H4> |
---|
78 | The first form indicates that a partial update of the object is |
---|
79 | needed. The bits in mask are OR'd into <TT>damage()</TT>. Your <TT> |
---|
80 | draw()</TT> routine can examine these bits to limit what it is |
---|
81 | drawing. The public method <TT>Fl_Widget::redraw()</TT> simply does |
---|
82 | <TT> Fl_Widget::damage(FL_DAMAGE_ALL)</TT>, but the implementation of |
---|
83 | your widget can call the private <TT>damage(n)</TT>. |
---|
84 | <P>The second form indicates that a region is damaged. If only these |
---|
85 | calls are done in a window (no calls to <TT>damage(n)</TT>) then FLTK |
---|
86 | will clip to the union of all these calls before drawing anything. |
---|
87 | This can greatly speed up incremental displays. The mask bits are |
---|
88 | OR'd into <TT>damage()</TT> unless this is a <TT>Fl_Window</TT> widget. </P> |
---|
89 | <P>The third form returns the bitwise-OR of all <TT>damage(n)</TT> |
---|
90 | calls done since the last <TT>draw()</TT>.</P> |
---|
91 | <P><I>When redrawing your widgets you should look at the damage bits to |
---|
92 | see what parts of your widget need redrawing.</I> The <tt>handle()</tt> |
---|
93 | method can then set individual damage bits to limit the amount of drawing |
---|
94 | that needs to be done: |
---|
95 | <UL><PRE> |
---|
96 | MyClass::handle(int event) { |
---|
97 | ... |
---|
98 | if (change_to_part1) damage(1); |
---|
99 | if (change_to_part2) damage(2); |
---|
100 | if (change_to_part3) damage(4); |
---|
101 | } |
---|
102 | |
---|
103 | MyClass::draw() { |
---|
104 | if (damage() & FL_DAMAGE_ALL) { |
---|
105 | ... draw frame/box and other static stuff ... |
---|
106 | } |
---|
107 | |
---|
108 | if (damage() & (FL_DAMAGE_ALL | 1)) draw_part1(); |
---|
109 | if (damage() & (FL_DAMAGE_ALL | 2)) draw_part2(); |
---|
110 | if (damage() & (FL_DAMAGE_ALL | 4)) draw_part3(); |
---|
111 | } |
---|
112 | </PRE></UL> |
---|
113 | <H4><A name=draw_box>void Fl_Widget::draw_box() const |
---|
114 | <BR></A>void Fl_Widget::draw_box(Fl_Boxtype b, ulong c) const</H4> |
---|
115 | The first form draws this widget's <TT>box()</TT>, using the |
---|
116 | dimensions of the widget. The second form uses <TT>b</TT> as the box |
---|
117 | type and <TT>c</TT> as the color for the box. |
---|
118 | |
---|
119 | <H4><A name="draw_focus">void Fl_Widget::draw_focus() const |
---|
120 | <BR>void Fl_Widget::draw_focus(Fl_Boxtype b, int x, int y, int w, int h) const</A></H4> |
---|
121 | |
---|
122 | <P>Draws a focus box inside the widgets bounding box. The second |
---|
123 | form allows you to specify a different bounding box. |
---|
124 | |
---|
125 | <H4><A name=draw_label>void Fl_Widget::draw_label() const |
---|
126 | <BR> void Fl_Widget::draw_label(int x, int y, int w, int h) const |
---|
127 | <BR> void Fl_Widget::draw_label(int x, int y, int w, int h, Fl_Align |
---|
128 | align) const</A></H4> |
---|
129 | This is the usual function for a <TT>draw()</TT> method to call to |
---|
130 | draw the widget's label. It does not draw the label if it is supposed |
---|
131 | to be outside the box (on the assumption that the enclosing group will |
---|
132 | draw those labels). |
---|
133 | <P>The second form uses the passed bounding box instead of the widget's |
---|
134 | bounding box. This is useful so "centered" labels are aligned with some |
---|
135 | feature, like a moving slider. </P> |
---|
136 | <P>The third form draws the label anywhere. It acts as though <TT> |
---|
137 | FL_ALIGN_INSIDE</TT> has been forced on so the label will appear inside |
---|
138 | the passed bounding box. This is designed for parent groups to draw |
---|
139 | labels with. </P> |
---|
140 | <H4><A name=set_flag>void Fl_Widget::set_flag(SHORTCUT_LABEL)</A></H4> |
---|
141 | Modifies <TT>draw_label()</TT> so that '&' characters cause an underscore |
---|
142 | to be printed under the next letter. |
---|
143 | <H4><A name=set_visible>void Fl_Widget::set_visible()</A> |
---|
144 | <BR><A name=clear_visible>void Fl_Widget::clear_visible()</A></H4> |
---|
145 | Fast inline versions of <TT>Fl_Widget::hide()</TT> and <TT> |
---|
146 | Fl_Widget::show()</TT>. These do not send the <TT>FL_HIDE</TT> and <TT> |
---|
147 | FL_SHOW</TT> events to the widget. |
---|
148 | <H4><A name=test_shortcut>int Fl_Widget::test_shortcut() const |
---|
149 | <BR> static int Fl_Widget::test_shortcut(const char *s)</A></H4> |
---|
150 | The first version tests <TT>Fl_Widget::label()</TT> against the |
---|
151 | current event (which should be a <TT>FL_SHORTCUT</TT> event). If the |
---|
152 | label contains a '&' character and the character after it matches the key |
---|
153 | press, this returns true. This returns false if the <TT>SHORTCUT_LABEL</TT> |
---|
154 | flag is off, if the label is <TT>NULL</TT> or does not have a |
---|
155 | '&' character in it, or if the keypress does not match the character. |
---|
156 | <P>The second version lets you do this test against an arbitrary |
---|
157 | string. </P> |
---|
158 | <H4><A name=type>uchar Fl_Widget::type() const |
---|
159 | <BR> void Fl_Widget::type(uchar t)</A></H4> |
---|
160 | The property <TT>Fl_Widget::type()</TT> can return an arbitrary 8-bit |
---|
161 | identifier, and can be set with the protected method <TT>type(uchar t)</TT> |
---|
162 | . This value had to be provided for Forms compatibility, but you can |
---|
163 | use it for any purpose you want. Try to keep the value less than 100 |
---|
164 | to not interfere with reserved values. |
---|
165 | <P>FLTK does not use RTTI (Run Time Typing Information), to enhance |
---|
166 | portability. But this may change in the near future if RTTI becomes |
---|
167 | standard everywhere. </P> |
---|
168 | <P>If you don't have RTTI you can use the clumsy FLTK mechanism, by |
---|
169 | having <TT>type()</TT> use a unique value. These unique values must |
---|
170 | be greater than the symbol <TT>FL_RESERVED_TYPE</TT> (which is 100). |
---|
171 | Look through the header files for <TT>FL_RESERVED_TYPE</TT> to find an |
---|
172 | unused number. If you make a subclass of <TT>Fl_Window</TT> |
---|
173 | you must use <TT>FL_WINDOW + n</TT> (<TT>n</tt> must be in the |
---|
174 | range 1 to 7). </P> |
---|
175 | <H2><A NAME="handle">Handling Events</A></H2> |
---|
176 | The virtual method <TT>int Fl_Widget::handle(int event)</TT> is called |
---|
177 | to handle each event passed to the widget. It can: |
---|
178 | <UL> |
---|
179 | <LI>Change the state of the widget. </LI> |
---|
180 | <LI>Call <A href=Fl_Widget.html#Fl_Widget.redraw><TT>Fl_Widget::redraw()</TT> |
---|
181 | </A> if the widget needs to be redisplayed. </LI> |
---|
182 | <LI>Call <A href=Fl_Widget.html#Fl_Widget.damage><TT> |
---|
183 | Fl_Widget::damage(n)</TT></A> if the widget needs a partial-update |
---|
184 | (assuming you provide support for this in your <A HREF="#draw"><TT>Fl_Widget::draw()</TT></A> |
---|
185 | method). </LI> |
---|
186 | <LI>Call <A href=Fl_Widget.html#Fl_Widget.do_callback><TT> |
---|
187 | Fl_Widget::do_callback()</TT></A> if a callback should be generated. </LI> |
---|
188 | <LI>Call <TT>Fl_Widget::handle()</TT> on child widgets. </LI> |
---|
189 | </UL> |
---|
190 | Events are identified by the integer argument. Other information |
---|
191 | about the most recent event is stored in static locations and aquired |
---|
192 | by calling the <A href=events.html#events><TT>Fl::event_*()</TT></A> |
---|
193 | functions. This information remains valid until another event is |
---|
194 | handled. |
---|
195 | <P>Here is a sample <TT>handle()</TT> method for a widget that acts as |
---|
196 | a pushbutton and also accepts the keystroke 'x' to cause the callback: </P> |
---|
197 | <UL><PRE> |
---|
198 | int MyClass::handle(int event) { |
---|
199 | switch(event) { |
---|
200 | case FL_PUSH: |
---|
201 | highlight = 1; |
---|
202 | redraw(); |
---|
203 | return 1; |
---|
204 | case FL_DRAG: { |
---|
205 | int t = Fl::event_inside(this); |
---|
206 | if (t != highlight) { |
---|
207 | highlight = t; |
---|
208 | redraw(); |
---|
209 | } |
---|
210 | } |
---|
211 | return 1; |
---|
212 | case FL_RELEASE: |
---|
213 | if (highlight) { |
---|
214 | highlight = 0; |
---|
215 | redraw(); |
---|
216 | do_callback(); |
---|
217 | // never do anything after a callback, as the callback |
---|
218 | // may delete the widget! |
---|
219 | } |
---|
220 | return 1; |
---|
221 | case FL_SHORTCUT: |
---|
222 | if (Fl::event_key() == 'x') { |
---|
223 | do_callback(); |
---|
224 | return 1; |
---|
225 | } |
---|
226 | return 0; |
---|
227 | default: |
---|
228 | return Fl_Widget::handle(event); |
---|
229 | } |
---|
230 | } |
---|
231 | </PRE></UL> |
---|
232 | |
---|
233 | <P>You must return non-zero if your <TT>handle()</TT> method |
---|
234 | uses the event. If you return zero, the parent widget will try |
---|
235 | sending the event to another widget. |
---|
236 | |
---|
237 | <H2><A NAME="draw">Drawing the Widget</A></H2> |
---|
238 | |
---|
239 | <P>The <TT>draw()</TT> virtual method is called when FLTK wants |
---|
240 | you to redraw your widget. It will be called if and only if |
---|
241 | <TT>damage()</TT> is non-zero, and <TT>damage()</TT> will be |
---|
242 | cleared to zero after it returns. The <TT>draw()</TT> method |
---|
243 | should be declared protected so that it can't be called from |
---|
244 | non-drawing code. |
---|
245 | |
---|
246 | <P>The <TT>damage()</TT> value contains the bitwise-OR of all |
---|
247 | the <TT>damage(n)</TT> calls to this widget since it was last |
---|
248 | drawn. This can be used for minimal update, by only redrawing |
---|
249 | the parts whose bits are set. FLTK will turn on the |
---|
250 | <TT>FL_DAMAGE_ALL</TT> bit if it thinks the entire widget must |
---|
251 | be redrawn, e.g. for an expose event. </P> |
---|
252 | |
---|
253 | <P>Expose events (and the above <TT>damage(b,x,y,w,h)</TT>) will cause <TT> |
---|
254 | draw()</TT> to be called with FLTK's <A href=drawing.html#clipping> |
---|
255 | clipping</A> turned on. You can greatly speed up redrawing in some |
---|
256 | cases by testing <TT>fl_not_clipped(x,y,w,h)</TT> or <TT>fl_clip_box(...)</TT> and |
---|
257 | skipping invisible parts. </P> |
---|
258 | <P>Besides the protected methods described above, FLTK provides a large |
---|
259 | number of basic drawing functions, which are described <A href=drawing.html#drawing> |
---|
260 | below</A>. </P> |
---|
261 | <H2>Resizing the Widget</H2> |
---|
262 | The <TT>resize(int x, int y, int w, int h)</TT> method is called when |
---|
263 | the widget is being resized or moved. The arguments are the new |
---|
264 | position, width, and height. <TT>x()</TT>, <TT>y()</TT>, <TT>w()</TT>, |
---|
265 | and <TT>h()</TT> still remain the old size. You must call <TT>resize()</TT> |
---|
266 | on your base class with the same arguments to get the widget size to |
---|
267 | actually change. |
---|
268 | <P>This should <I>not</I> call <TT>redraw()</TT>, at least if only the <TT> |
---|
269 | x()</TT> and <TT>y()</TT> change. This is because composite widgets like <A href=Fl_Scroll.html#Fl_Scroll> |
---|
270 | <TT>Fl_Scroll</TT></A> may have a more efficient way of drawing the new |
---|
271 | position. </P> |
---|
272 | <H2>Making a Composite Widget</H2> |
---|
273 | A "composite" widget contains one or more "child" widgets. |
---|
274 | To make a composite widget you should subclass <A href=Fl_Group.html#Fl_Group><TT>Fl_Group</TT></A> |
---|
275 | . It is possible to make a composite object that is not a subclass of <TT> |
---|
276 | Fl_Group</TT>, but you'll have to duplicate the code in <TT>Fl_Group</TT> |
---|
277 | anyways. |
---|
278 | <P>Instances of the child widgets may be included in the parent: </P> |
---|
279 | <UL><PRE> |
---|
280 | class MyClass : public Fl_Group { |
---|
281 | Fl_Button the_button; |
---|
282 | Fl_Slider the_slider; |
---|
283 | ... |
---|
284 | }; |
---|
285 | </PRE></UL> |
---|
286 | The constructor has to initialize these instances. They are |
---|
287 | automatically <TT>add()</TT>ed to the group, since the <TT>Fl_Group</TT> |
---|
288 | constructor does <TT>begin()</TT>. <I>Don't forget to call <TT>end()</TT> |
---|
289 | or use the <A href=Fl_End.html#Fl_End><TT>Fl_End</TT></A> pseudo-class:</I> |
---|
290 | <UL><PRE> |
---|
291 | MyClass::MyClass(int x, int y, int w, int h) : |
---|
292 | Fl_Group(x, y, w, h), |
---|
293 | the_button(x + 5, y + 5, 100, 20), |
---|
294 | the_slider(x, y + 50, w, 20) |
---|
295 | { |
---|
296 | ...(you could add dynamically created child widgets here)... |
---|
297 | end(); // don't forget to do this! |
---|
298 | } |
---|
299 | </PRE></UL> |
---|
300 | The child widgets need callbacks. These will be called with a pointer |
---|
301 | to the children, but the widget itself may be found in the <TT>parent()</TT> |
---|
302 | pointer of the child. Usually these callbacks can be static private |
---|
303 | methods, with a matching private method: |
---|
304 | <UL><PRE> |
---|
305 | void MyClass::static_slider_cb(Fl_Widget* v, void *) { // static method |
---|
306 | ((MyClass*)(v->parent())->slider_cb(); |
---|
307 | } |
---|
308 | void MyClass::slider_cb() { // normal method |
---|
309 | use(the_slider->value()); |
---|
310 | } |
---|
311 | </PRE></UL> |
---|
312 | If you make the <TT>handle()</TT> method, you can quickly pass all the |
---|
313 | events to the children using the <TT>Fl_Group::handle()</TT> method. |
---|
314 | You don't need to override <TT>handle()</TT> if your composite widget |
---|
315 | does nothing other than pass events to the children: |
---|
316 | <UL><PRE> |
---|
317 | int MyClass::handle(int event) { |
---|
318 | if (Fl_Group::handle(event)) return 1; |
---|
319 | ... handle events that children don't want ... |
---|
320 | } |
---|
321 | </PRE></UL> |
---|
322 | |
---|
323 | <P>If you override <TT>draw()</TT> you need to draw all the |
---|
324 | children. If <TT>redraw()</TT> or <TT>damage()</TT> is called |
---|
325 | on a child, <TT>damage(FL_DAMAGE_CHILD)</TT> is done to the |
---|
326 | group, so this bit of <TT>damage()</TT> can be used to indicate |
---|
327 | that a child needs to be drawn. It is fastest if you avoid |
---|
328 | drawing anything else in this case: |
---|
329 | |
---|
330 | <UL><PRE> |
---|
331 | int MyClass::draw() { |
---|
332 | Fl_Widget *const*a = array(); |
---|
333 | if (damage() == FL_DAMAGE_CHILD) { // only redraw some children |
---|
334 | for (int i = children(); i --; a ++) update_child(**a); |
---|
335 | } else { // total redraw |
---|
336 | ... draw background graphics ... |
---|
337 | // now draw all the children atop the background: |
---|
338 | for (int i = children_; i --; a ++) { |
---|
339 | draw_child(**a); |
---|
340 | draw_outside_label(**a); // you may not need to do this |
---|
341 | } |
---|
342 | } |
---|
343 | } |
---|
344 | </PRE></UL> |
---|
345 | <TT>Fl_Group</TT> provides some protected methods to make drawing |
---|
346 | easier: |
---|
347 | <UL> |
---|
348 | <LI><A href=#draw_child>draw_child</A></LI> |
---|
349 | <LI><A href=#draw_outside_label>draw_outside_label</A></LI> |
---|
350 | <LI><A href=#update_child>update_child</A></LI> |
---|
351 | </UL> |
---|
352 | <H4><A name=draw_child>void Fl_Group::draw_child(Fl_Widget&)</A></H4> |
---|
353 | This will force the child's <TT>damage()</TT> bits all to one and call <TT> |
---|
354 | draw()</TT> on it, then clear the <TT>damage()</TT>. You should call |
---|
355 | this on all children if a total redraw of your widget is requested, or |
---|
356 | if you draw something (like a background box) that damages the child. |
---|
357 | Nothing is done if the child is not <TT>visible()</TT> or if it is |
---|
358 | clipped. |
---|
359 | <H4><A name=draw_outside_label>void |
---|
360 | Fl_Group::draw_outside_label(Fl_Widget&) const</A></H4> |
---|
361 | Draw the labels that are <I>not</I> drawn by <A href=#draw_label><TT> |
---|
362 | draw_label()</TT></A>. If you want more control over the label |
---|
363 | positions you might want to call <TT>child->draw_label(x,y,w,h,a)</TT>. |
---|
364 | <H4><A name=update_child>void Fl_Group::update_child(Fl_Widget&)</A></H4> |
---|
365 | Draws the child only if its <TT>damage()</TT> is non-zero. You |
---|
366 | should call this on all the children if your own damage is equal to |
---|
367 | FL_DAMAGE_CHILD. Nothing is done if the child is not <TT>visible()</TT> |
---|
368 | or if it is clipped. |
---|
369 | |
---|
370 | <H2>Cut and Paste Support</H2> |
---|
371 | FLTK provides routines to cut and paste 8-bit text (in the future this |
---|
372 | may be UTF-8) between applications: |
---|
373 | <UL> |
---|
374 | <LI><A href="Fl.html#Fl.paste"><TT>Fl::paste</TT></A></LI> |
---|
375 | <LI><A href="Fl.html#Fl.selection"><TT>Fl::selection</TT></A></LI> |
---|
376 | <LI><A href="Fl.html#Fl.selection_owner"><TT>Fl::selection_owner</TT></A></LI> |
---|
377 | </UL> |
---|
378 | It may be possible to cut/paste non-text data by using <A href=osissues.html#add_handler> |
---|
379 | <TT>Fl::add_handler()</TT></A>. |
---|
380 | |
---|
381 | <H2>Drag And Drop Support</H2> |
---|
382 | |
---|
383 | FLTK provides routines to drag and drop 8-bit text between applications: |
---|
384 | |
---|
385 | <P>Drag'n'drop operations are are initiated by copying data to the |
---|
386 | clipboard and calling the function |
---|
387 | <A href="Fl.html#Fl.dnd"><TT>Fl::dnd()</TT></A>. |
---|
388 | |
---|
389 | <P>Drop attempts are handled via <A href="events.html#dnd">events</A>: |
---|
390 | <UL> |
---|
391 | <LI><TT>FL_DND_ENTER</TT></LI> |
---|
392 | <LI><TT>FL_DND_DRAG</TT></LI> |
---|
393 | <LI><TT>FL_DND_LEAVE</TT></LI> |
---|
394 | <LI><TT>FL_DND_RELEASE</TT></LI> |
---|
395 | <LI><TT>FL_PASTE</TT></LI> |
---|
396 | </UL> |
---|
397 | |
---|
398 | <H2>Making a subclass of Fl_Window</H2> |
---|
399 | |
---|
400 | <P>You may want your widget to be a subclass of |
---|
401 | <TT>Fl_Window</TT>, <TT>Fl_Double_Window</TT>, or |
---|
402 | <TT>FL_Gl_Window</TT>. This can be useful if your widget wants |
---|
403 | to occupy an entire window, and can also be used to take |
---|
404 | advantage of system-provided clipping, or to work with a library |
---|
405 | that expects a system window ID to indicate where to draw. |
---|
406 | |
---|
407 | <P>Subclassing <TT>Fl_Window</TT>is almost exactly like |
---|
408 | subclassing <TT>Fl_Group</TT>, and in fact you can easily |
---|
409 | switch a subclass back and forth. Watch out for the following |
---|
410 | differences: </P> |
---|
411 | |
---|
412 | <OL> |
---|
413 | |
---|
414 | <LI><TT>Fl_Window</TT> is a subclass of |
---|
415 | <TT>Fl_Group</TT> so <I>make sure your constructor calls |
---|
416 | <TT>end()</TT></I> unless you actually want children |
---|
417 | added to your window.</LI> |
---|
418 | |
---|
419 | <LI>When handling events and drawing, the upper-left |
---|
420 | corner is at 0,0, not <TT>x(),y()</TT> as in other |
---|
421 | <TT>Fl_Widget</TT>'s. For instance, to draw a box |
---|
422 | around the widget, call <TT>draw_box(0, 0, w(), |
---|
423 | h())</TT>, rather than <TT>draw_box(x(), y(), w(), |
---|
424 | h())</TT>.</LI> |
---|
425 | |
---|
426 | </OL> |
---|
427 | |
---|
428 | <P>You may also want to subclass <TT>Fl_Window</TT> in order to |
---|
429 | get access to different visuals or to change other attributes of |
---|
430 | the windows. See <A href="osissues.html">"Appendix F - Operating |
---|
431 | System Issues"</A> for more information. |
---|
432 | |
---|
433 | </BODY> |
---|
434 | </HTML> |
---|