source: rtems-graphics-toolkit/fltk-1.1.10/fluid/Fl_Window_Type.cxx @ 513eea1

Last change on this file since 513eea1 was 513eea1, checked in by Joel Sherrill <joel.sherrill@…>, on 01/09/10 at 22:43:24

2010-01-08 Joel Sherrill <joel.sherrill@…>

fltk 1.1.10. imported

  • ORIGIN: Updated.
  • Property mode set to 100644
File size: 41.6 KB
Line 
1//
2// "$Id$"
3//
4// Window type code for the Fast Light Tool Kit (FLTK).
5//
6// The widget describing an Fl_Window.  This is also all the code
7// for interacting with the overlay, which allows the user to
8// select, move, and resize the children widgets.
9//
10// Copyright 1998-2006 by Bill Spitzak and others.
11//
12// This library is free software; you can redistribute it and/or
13// modify it under the terms of the GNU Library General Public
14// License as published by the Free Software Foundation; either
15// version 2 of the License, or (at your option) any later version.
16//
17// This library is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20// Library General Public License for more details.
21//
22// You should have received a copy of the GNU Library General Public
23// License along with this library; if not, write to the Free Software
24// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25// USA.
26//
27// Please report all bugs and problems on the following page:
28//
29//     http://www.fltk.org/str.php
30//
31
32#include <FL/Fl.H>
33#include <FL/Fl_Overlay_Window.H>
34#include <FL/fl_message.H>
35#include <FL/fl_draw.H>
36#include <FL/x.H>
37#include <FL/Fl_Menu_Item.H>
38#include <FL/Fl_Round_Button.H>
39#include "Fl_Widget_Type.h"
40#include "undo.h"
41#include <math.h>
42#include <stdlib.h>
43#include "alignment_panel.h"
44#include <stdio.h>
45
46extern int gridx;
47extern int gridy;
48extern int snap;
49extern int show_guides;
50
51int include_H_from_C = 1;
52int use_FL_COMMAND = 0;
53extern int i18n_type;
54extern const char* i18n_include;
55extern const char* i18n_function;
56extern const char* i18n_file;
57extern const char* i18n_set;
58
59extern Fl_Preferences   fluid_prefs;
60
61inline int fl_min(int a, int b) { return (a < b ? a : b); }
62
63#include "widget_panel.h"
64
65// Update the XYWH values in the widget panel...
66static void update_xywh() {
67  if (current_widget && current_widget->is_widget()) {
68    widget_x_input->value(((Fl_Widget_Type *)current_widget)->o->x());
69    widget_y_input->value(((Fl_Widget_Type *)current_widget)->o->y());
70    widget_w_input->value(((Fl_Widget_Type *)current_widget)->o->w());
71    widget_h_input->value(((Fl_Widget_Type *)current_widget)->o->h());
72  }
73}
74
75void guides_cb(Fl_Check_Button *i, long) {
76  show_guides = i->value();
77  fluid_prefs.set("show_guides", show_guides);
78
79  for (Fl_Type *p = Fl_Type::first; p; p = p->next) {
80    if (p->is_window()) {
81      Fl_Window_Type *w = (Fl_Window_Type *)p;
82      ((Fl_Overlay_Window *)(w->o))->redraw_overlay();
83    }
84  }
85}
86
87void grid_cb(Fl_Input *i, long v) {
88  int n = atoi(i->value());
89  if (n < 0) n = 0;
90  switch (v) {
91    case 1:
92      gridx = n;
93      fluid_prefs.set("gridx", n);
94      break;
95    case 2:
96      gridy = n;
97      fluid_prefs.set("gridy", n);
98      break;
99    case 3:
100      snap = n;
101      fluid_prefs.set("snap", n);
102      break;
103  }
104
105  // Next go through all of the windows in the project and set the
106  // stepping for resizes...
107  Fl_Type *p;
108  Fl_Window_Type *w;
109
110  for (p = Fl_Type::first; p; p = p->next) {
111    if (p->is_window()) {
112      w = (Fl_Window_Type *)p;
113      ((Fl_Window *)(w->o))->size_range(gridx, gridy,
114                                        Fl::w(), Fl::h(),
115                                        gridx, gridy, 0);
116    }
117  }
118}
119
120// Set default widget sizes...
121void default_widget_size_cb(Fl_Round_Button *b, long size) {
122  // Update the "normal" text size of new widgets...
123  b->setonly();
124  Fl_Widget_Type::default_size = size;
125  fluid_prefs.set("widget_size", Fl_Widget_Type::default_size);
126}
127
128
129void i18n_type_cb(Fl_Choice *c, void *) {
130  undo_checkpoint();
131
132  switch (i18n_type = c->value()) {
133  case 0 : /* None */
134      i18n_include_input->hide();
135      i18n_file_input->hide();
136      i18n_set_input->hide();
137      i18n_function_input->hide();
138      break;
139  case 1 : /* GNU gettext */
140      i18n_include_input->value("<libintl.h>");
141      i18n_include = i18n_include_input->value();
142      i18n_function_input->value("gettext");
143      i18n_function = i18n_function_input->value();
144      i18n_include_input->show();
145      i18n_file_input->hide();
146      i18n_set_input->hide();
147      i18n_function_input->show();
148      break;
149  case 2 : /* POSIX cat */
150      i18n_include_input->value("<nl_types.h>");
151      i18n_file_input->value("");
152      i18n_file = i18n_file_input->value();
153      i18n_set_input->value("1");
154      i18n_set = i18n_set_input->value();
155      i18n_include_input->show();
156      i18n_include = i18n_include_input->value();
157      i18n_file_input->show();
158      i18n_set_input->show();
159      i18n_function_input->hide();
160      break;
161  }
162
163  set_modflag(1);
164}
165
166void i18n_text_cb(Fl_Input *i, void *) {
167  undo_checkpoint();
168
169  if (i == i18n_function_input)
170    i18n_function = i->value();
171  else if (i == i18n_file_input)
172    i18n_file = i->value();
173  else if (i == i18n_set_input)
174    i18n_set = i->value();
175  else if (i == i18n_include_input)
176    i18n_include = i->value();
177
178  set_modflag(1);
179}
180
181extern const char* header_file_name;
182extern const char* code_file_name;
183
184void show_project_cb(Fl_Widget *, void *) {
185  if(project_window==0) make_project_window();
186  include_H_from_C_button->value(include_H_from_C);
187  use_FL_COMMAND_button->value(use_FL_COMMAND);
188  header_file_input->value(header_file_name);
189  code_file_input->value(code_file_name);
190  i18n_type_chooser->value(i18n_type);
191  i18n_function_input->value(i18n_function);
192  i18n_file_input->value(i18n_file);
193  i18n_set_input->value(i18n_set);
194  i18n_include_input->value(i18n_include);
195  switch (i18n_type) {
196  case 0 : /* None */
197      i18n_include_input->hide();
198      i18n_file_input->hide();
199      i18n_set_input->hide();
200      i18n_function_input->hide();
201      break;
202  case 1 : /* GNU gettext */
203      i18n_include_input->show();
204      i18n_file_input->hide();
205      i18n_set_input->hide();
206      i18n_function_input->show();
207      break;
208  case 2 : /* POSIX cat */
209      i18n_include_input->show();
210      i18n_file_input->show();
211      i18n_set_input->show();
212      i18n_function_input->hide();
213      break;
214  }
215  project_window->hotspot(project_window);
216  project_window->show();
217}
218
219void show_grid_cb(Fl_Widget *, void *) {
220  char buf[128];
221  sprintf(buf,"%d",gridx); horizontal_input->value(buf);
222  sprintf(buf,"%d",gridy); vertical_input->value(buf);
223  sprintf(buf,"%d",snap); snap_input->value(buf);
224  guides_toggle->value(show_guides);
225  int s = Fl_Widget_Type::default_size;
226  if (s<=8) def_widget_size[0]->setonly();
227  else if (s<=11) def_widget_size[1]->setonly();
228  else if (s<=14) def_widget_size[2]->setonly();
229  else if (s<=18) def_widget_size[3]->setonly();
230  else if (s<=24) def_widget_size[4]->setonly();
231  else if (s<=32) def_widget_size[5]->setonly();
232  grid_window->hotspot(grid_window);
233  grid_window->show();
234}
235
236void show_settings_cb(Fl_Widget *, void *) {
237  settings_window->hotspot(settings_window);
238  settings_window->show();
239}
240
241void header_input_cb(Fl_Input* i, void*) {
242  if (header_file_name && strcmp(header_file_name, i->value()))
243    set_modflag(1);
244  header_file_name = i->value();
245}
246void code_input_cb(Fl_Input* i, void*) {
247  if (code_file_name && strcmp(code_file_name, i->value()))
248    set_modflag(1);
249  code_file_name = i->value();
250}
251
252void include_H_from_C_button_cb(Fl_Check_Button* b, void*) {
253  if (include_H_from_C != b->value()) {
254    set_modflag(1);
255    include_H_from_C = b->value();
256  }
257}
258
259void use_FL_COMMAND_button_cb(Fl_Check_Button* b, void*) {
260  if (use_FL_COMMAND != b->value()) {
261    set_modflag(1);
262    use_FL_COMMAND = b->value();
263  }
264}
265
266////////////////////////////////////////////////////////////////
267
268Fl_Menu_Item window_type_menu[] = {
269  {"Single",0,0,(void*)FL_WINDOW},
270  {"Double",0,0,(void*)(FL_WINDOW+1)},
271  {0}};
272
273static int overlays_invisible;
274
275// The following Fl_Widget is used to simulate the windows.  It has
276// an overlay for the fluid ui, and special-cases the FL_NO_BOX.
277
278class Overlay_Window : public Fl_Overlay_Window {
279  void draw();
280  void draw_overlay();
281public:
282  Fl_Window_Type *window;
283  int handle(int);
284  Overlay_Window(int W,int H) : Fl_Overlay_Window(W,H) {Fl_Group::current(0);}
285  void resize(int,int,int,int);
286  uchar *read_image(int &ww, int &hh);
287};
288void Overlay_Window::draw() {
289  const int CHECKSIZE = 8;
290  // see if box is clear or a frame or rounded:
291  if ((damage()&FL_DAMAGE_ALL) &&
292      (!box() || (box()>=4&&!(box()&2)) || box()>=_FL_ROUNDED_BOX)) {
293    // if so, draw checkerboard so user can see what areas are clear:
294    for (int Y = 0; Y < h(); Y += CHECKSIZE)
295      for (int X = 0; X < w(); X += CHECKSIZE) {
296        fl_color(((Y/(2*CHECKSIZE))&1) != ((X/(2*CHECKSIZE))&1) ?
297                 FL_WHITE : FL_BLACK);
298        fl_rectf(X,Y,CHECKSIZE,CHECKSIZE);
299      }
300  }
301  Fl_Overlay_Window::draw();
302}
303
304extern Fl_Window *main_window;
305
306// Read an image of the overlay window
307uchar *Overlay_Window::read_image(int &ww, int &hh) {
308  // Create an off-screen buffer for the window...
309  main_window->make_current();
310
311  ww = w();
312  hh = h();
313
314  Fl_Offscreen offscreen = fl_create_offscreen(ww, hh);
315  uchar *pixels;
316
317  // Redraw the window into the offscreen buffer...
318  fl_begin_offscreen(offscreen);
319
320  if (!shown()) image(Fl::scheme_bg_);
321
322  redraw();
323  draw();
324
325  // Read the screen image...
326  pixels = fl_read_image(0, 0, 0, ww, hh);
327
328  fl_end_offscreen();
329
330  // Cleanup and return...
331  fl_delete_offscreen(offscreen);
332
333  return pixels;
334}
335
336void Overlay_Window::draw_overlay() {
337  window->draw_overlay();
338}
339int Overlay_Window::handle(int e) {
340  int ret =  window->handle(e);
341  if (ret==0) {
342    switch (e) {
343      case FL_SHOW:
344      case FL_HIDE:
345        ret = Fl_Overlay_Window::handle(e);
346    }
347  }
348  return ret;
349}
350
351Fl_Type *Fl_Window_Type::make() {
352  Fl_Type *p = Fl_Type::current;
353  while (p && !p->is_code_block()) p = p->parent;
354  if (!p) {
355    fl_message("Please select a function");
356    return 0;
357  }
358  Fl_Window_Type *myo = new Fl_Window_Type();
359  if (!this->o) {// template widget
360    this->o = new Fl_Window(100,100);
361    Fl_Group::current(0);
362  }
363  // Set the size ranges for this window; in order to avoid opening the
364  // X display we use an arbitrary maximum size...
365  ((Fl_Window *)(this->o))->size_range(gridx, gridy,
366                                       3072, 2048,
367                                       gridx, gridy, 0);
368  myo->factory = this;
369  myo->drag = 0;
370  myo->numselected = 0;
371  Overlay_Window *w = new Overlay_Window(100,100);
372  w->window = myo;
373  myo->o = w;
374  myo->add(p);
375  myo->modal = 0;
376  myo->non_modal = 0;
377  return myo;
378}
379
380void Fl_Window_Type::add_child(Fl_Type* cc, Fl_Type* before) {
381  if (!cc->is_widget()) return;
382  Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
383  Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
384  ((Fl_Window*)o)->insert(*(c->o), b);
385  o->redraw();
386}
387
388void Fl_Window_Type::remove_child(Fl_Type* cc) {
389  Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
390  ((Fl_Window*)o)->remove(c->o);
391  o->redraw();
392}
393
394void Fl_Window_Type::move_child(Fl_Type* cc, Fl_Type* before) {
395  Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
396  ((Fl_Window*)o)->remove(c->o);
397  Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
398  ((Fl_Window*)o)->insert(*(c->o), b);
399  o->redraw();
400}
401
402////////////////////////////////////////////////////////////////
403
404// Double-click on window widget shows the window, or if already shown,
405// it shows the control panel.
406void Fl_Window_Type::open() {
407  Overlay_Window *w = (Overlay_Window *)o;
408  if (w->shown()) {
409    w->show();
410    Fl_Widget_Type::open();
411  } else {
412    Fl_Widget *p = w->resizable();
413    if (!p) w->resizable(w);
414    w->show();
415    w->resizable(p);
416  }
417
418  w->image(Fl::scheme_bg_);
419  w->size_range(gridx, gridy, Fl::w(), Fl::h(), gridx, gridy, 0);
420}
421
422// Read an image of the window
423uchar *Fl_Window_Type::read_image(int &ww, int &hh) {
424  Overlay_Window *w = (Overlay_Window *)o;
425
426  // Read the screen image...
427  return (w->read_image(ww, hh));
428}
429
430
431// control panel items:
432
433void modal_cb(Fl_Light_Button* i, void* v) {
434  if (v == LOAD) {
435    if (!current_widget->is_window()) {i->hide(); return;}
436    i->show();
437    i->value(((Fl_Window_Type *)current_widget)->modal);
438  } else {
439    ((Fl_Window_Type *)current_widget)->modal = i->value();
440    set_modflag(1);
441  }
442}
443
444void non_modal_cb(Fl_Light_Button* i, void* v) {
445  if (v == LOAD) {
446    if (!current_widget->is_window()) {i->hide(); return;}
447    i->show();
448    i->value(((Fl_Window_Type *)current_widget)->non_modal);
449  } else {
450    ((Fl_Window_Type *)current_widget)->non_modal = i->value();
451    set_modflag(1);
452  }
453}
454
455void border_cb(Fl_Light_Button* i, void* v) {
456  if (v == LOAD) {
457    if (!current_widget->is_window()) {i->hide(); return;}
458    i->show();
459    i->value(((Fl_Window*)(current_widget->o))->border());
460  } else {
461    ((Fl_Window*)(current_widget->o))->border(i->value());
462    set_modflag(1);
463  }
464}
465
466void xclass_cb(Fl_Input* i, void* v) {
467  if (v == LOAD) {
468    if (!current_widget->is_window()) {
469      i->hide();
470      i->parent()->hide(); // hides the "X Class:" label as well
471      return;
472    }
473    i->show();
474    i->parent()->show();
475    i->value(((Fl_Widget_Type *)current_widget)->xclass);
476  } else {
477    int mod = 0;
478    for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
479      if (o->selected && o->is_widget()) {
480        mod = 1;
481        Fl_Widget_Type* w = (Fl_Widget_Type*)o;
482        if (w->is_window() || w->is_button())
483          storestring(i->value(),w->xclass);
484        if (w->is_window()) ((Fl_Window*)(w->o))->xclass(w->xclass);
485        else if (w->is_menu_item()) w->redraw();
486      }
487    }
488    if (mod) set_modflag(1);
489  }
490}
491
492////////////////////////////////////////////////////////////////
493
494void Fl_Window_Type::setlabel(const char *n) {
495  if (o) ((Fl_Window *)o)->label(n);
496}
497
498// make() is called on this widget when user picks window off New menu:
499Fl_Window_Type Fl_Window_type;
500
501// Resize from window manager...
502void Overlay_Window::resize(int X,int Y,int W,int H) {
503  Fl_Widget* t = resizable(); resizable(0);
504
505  // do not set the mod flag if the window was not resized. In FLUID, all
506  // windows are opened without a given x/y position, so modifying x/y
507  // should not mark the project as dirty
508  if (W!=w() || H!=h())
509    set_modflag(1);
510
511  Fl_Overlay_Window::resize(X,Y,W,H);
512  resizable(t);
513  update_xywh();
514}
515
516// calculate actual move by moving mouse position (mx,my) to
517// nearest multiple of gridsize, and snap to original position
518void Fl_Window_Type::newdx() {
519  int mydx, mydy;
520  if (Fl::event_state(FL_ALT) || !snap) {
521    mydx = mx-x1;
522    mydy = my-y1;
523
524    if (abs(mydx) < 2 && abs(mydy) < 2) mydx = mydy = 0;
525  } else {
526    int dx0 = mx-x1;
527    int ix = (drag&RIGHT) ? br : bx;
528    mydx = gridx ? ((ix+dx0+gridx/2)/gridx)*gridx - ix : dx0;
529    if (dx0 > snap) {
530      if (mydx < 0) mydx = 0;
531    } else if (dx0 < -snap) {
532      if (mydx > 0) mydx = 0;
533    } else
534      mydx = 0;
535    int dy0 = my-y1;
536    int iy = (drag&BOTTOM) ? by : bt;
537    mydy = gridy ? ((iy+dy0+gridy/2)/gridy)*gridy - iy : dy0;
538    if (dy0 > snap) {
539      if (mydy < 0) mydy = 0;
540    } else if (dy0 < -snap) {
541      if (mydy > 0) mydy = 0;
542    } else
543      mydy = 0;
544  }
545
546  if (!(drag & (DRAG | BOX | LEFT | RIGHT))) {
547    mydx = 0;
548    dx = 0;
549  }
550
551  if (!(drag & (DRAG | BOX | TOP | BOTTOM))) {
552    mydy = 0;
553    dy = 0;
554  }
555
556  if (dx != mydx || dy != mydy) {
557    dx = mydx; dy = mydy;
558    ((Overlay_Window *)o)->redraw_overlay();
559  }
560}
561
562// Move a widget according to dx and dy calculated above
563void Fl_Window_Type::newposition(Fl_Widget_Type *myo,int &X,int &Y,int &R,int &T) {
564  X = myo->o->x();
565  Y = myo->o->y();
566  R = X+myo->o->w();
567  T = Y+myo->o->h();
568  if (!drag) return;
569  if (drag&DRAG) {
570    X += dx;
571    Y += dy;
572    R += dx;
573    T += dy;
574  } else {
575    if (drag&LEFT) if (X==bx) X += dx; else if (X<bx+dx) X = bx+dx;
576    if (drag&TOP) if (Y==by) Y += dy; else if (Y<by+dy) Y = by+dy;
577    if (drag&RIGHT) if (R==br) R += dx; else if (R>br+dx) R = br+dx;
578    if (drag&BOTTOM) if (T==bt) T += dy; else if (T>bt+dx) T = bt+dx;
579  }
580  if (R<X) {int n = X; X = R; R = n;}
581  if (T<Y) {int n = Y; Y = T; T = n;}
582}
583
584// draw a vertical arrow pointing toward y2
585static void draw_v_arrow(int x, int y1, int y2) {
586  int dy = (y1>y2) ? -1 : 1 ;
587  fl_yxline(x, y1, y2);
588  fl_xyline(x-4, y2, x+4);
589  fl_line(x-2, y2-dy*5, x, y2-dy);
590  fl_line(x+2, y2-dy*5, x, y2-dy);
591}
592
593static void draw_h_arrow(int x1, int y, int x2) {
594  int dx = (x1>x2) ? -1 : 1 ;
595  fl_xyline(x1, y, x2);
596  fl_yxline(x2, y-4, y+4);
597  fl_line(x2-dx*5, y-2, x2-dx, y);
598  fl_line(x2-dx*5, y+2, x2-dx, y);
599}
600
601static void draw_top_brace(const Fl_Widget *w) {
602  fl_yxline(w->x(), w->y()-2, w->y()+6);
603  fl_yxline(w->x()+w->w()-1, w->y()-2, w->y()+6);
604  fl_xyline(w->x()-2, w->y(), w->x()+w->w()+1);
605}
606
607static void draw_left_brace(const Fl_Widget *w) {
608  fl_xyline(w->x()-2, w->y(), w->x()+6);
609  fl_xyline(w->x()-2, w->y()+w->h()-1, w->x()+6);
610  fl_yxline(w->x(), w->y()-2, w->y()+w->h()+1);
611}
612
613static void draw_right_brace(const Fl_Widget *w) {
614  int xx = w->x() + w->w() - 1;
615  fl_xyline(xx-6, w->y(), xx+2);
616  fl_xyline(xx-6, w->y()+w->h()-1, xx+2);
617  fl_yxline(xx, w->y()-2, w->y()+w->h()+1);
618}
619
620static void draw_bottom_brace(const Fl_Widget *w) {
621  int yy = w->y() + w->h() - 1;
622  fl_yxline(w->x(), yy-6, yy+2);
623  fl_yxline(w->x()+w->w()-1, yy-6, yy+2);
624  fl_xyline(w->x()-2, yy, w->x()+w->w()+1);
625}
626
627static void draw_height(int x, int y, int b, Fl_Align a) {
628  char buf[16];
629  int h = b - y;
630  sprintf(buf, "%d", h);
631  fl_font(FL_HELVETICA, 9);
632  int lw = (int)fl_width(buf);
633  int lx;
634
635  b --;
636  if (h < 30) {
637    // Move height to the side...
638    if (a == FL_ALIGN_LEFT) lx = x - lw - 2;
639    else lx = x + 2;
640
641    fl_yxline(x, y, b);
642  } else {
643    // Put height inside the arrows...
644    lx = x - lw / 2;
645
646    fl_yxline(x, y, y + (h - 11) / 2);
647    fl_yxline(x, y + (h + 11) / 2, b);
648  }
649
650  // Draw the height...
651  fl_draw(buf, lx, y + (h + 9) / 2);
652
653  // Draw the arrowheads...
654  fl_line(x-2, y+5, x, y+1, x+2, y+5);
655  fl_line(x-2, b-5, x, b-1, x+2, b-5);
656
657  // Draw the end lines...
658  fl_xyline(x - 4, y, x + 4);
659  fl_xyline(x - 4, b, x + 4);
660}
661
662static void draw_width(int x, int y, int r, Fl_Align a) {
663  char buf[16];
664  int w = r-x;
665  sprintf(buf, "%d", w);
666  fl_font(FL_HELVETICA, 9);
667  int lw = (int)fl_width(buf);
668  int ly = y + 4;
669
670  r --;
671
672  if (lw > (w - 20)) {
673    // Move width above/below the arrows...
674    if (a == FL_ALIGN_TOP) ly -= 10;
675    else ly += 10;
676
677    fl_xyline(x, y, r);
678  } else {
679    // Put width inside the arrows...
680    fl_xyline(x, y, x + (w - lw - 2) / 2);
681    fl_xyline(x + (w + lw + 2) / 2, y, r);
682  }
683
684  // Draw the width...
685  fl_draw(buf, x + (w - lw) / 2, ly);
686
687  // Draw the arrowheads...
688  fl_line(x+5, y-2, x+1, y, x+5, y+2);
689  fl_line(r-5, y-2, r-1, y, r-5, y+2);
690
691  // Draw the end lines...
692  fl_yxline(x, y - 4, y + 4);
693  fl_yxline(r, y - 4, y + 4);
694}
695
696void Fl_Window_Type::draw_overlay() {
697  if (recalc) {
698    bx = o->w(); by = o->h(); br = 0; bt = 0;
699    numselected = 0;
700    for (Fl_Type *q=next; q && q->level>level; q=q->next)
701      if (q->selected && q->is_widget() && !q->is_menu_item()) {
702        numselected++;
703        Fl_Widget_Type* myo = (Fl_Widget_Type*)q;
704        if (myo->o->x() < bx) bx = myo->o->x();
705        if (myo->o->y() < by) by = myo->o->y();
706        if (myo->o->x()+myo->o->w() > br) br = myo->o->x()+myo->o->w();
707        if (myo->o->y()+myo->o->h() > bt) bt = myo->o->y()+myo->o->h();
708      }
709    recalc = 0;
710    sx = bx; sy = by; sr = br; st = bt;
711  }
712  fl_color(FL_RED);
713  if (drag==BOX && (x1 != mx || y1 != my)) {
714    int x = x1; int r = mx; if (x > r) {x = mx; r = x1;}
715    int y = y1; int b = my; if (y > b) {y = my; b = y1;}
716    fl_rect(x,y,r-x,b-y);
717  }
718  if (overlays_invisible && !drag) return;
719  if (selected) fl_rect(0,0,o->w(),o->h());
720  if (!numselected) return;
721  int mybx,myby,mybr,mybt;
722  int mysx,mysy,mysr,myst;
723  mybx = mysx = o->w(); myby = mysy = o->h(); mybr = mysr = 0; mybt = myst = 0;
724  Fl_Type *selection = 0L; // used to store the one selected widget (if n==1)
725  for (Fl_Type *q=next; q && q->level>level; q = q->next)
726    if (q->selected && q->is_widget() && !q->is_menu_item()) {
727      selection = q;
728      Fl_Widget_Type* myo = (Fl_Widget_Type*)q;
729      int x,y,r,t;
730      newposition(myo,x,y,r,t);
731      if (!show_guides || !drag || numselected != 1) fl_rect(x,y,r-x,t-y);
732      if (x < mysx) mysx = x;
733      if (y < mysy) mysy = y;
734      if (r > mysr) mysr = r;
735      if (t > myst) myst = t;
736      if (!(myo->o->align() & FL_ALIGN_INSIDE)) {
737        // Adjust left/right/top/bottom for top/bottom labels...
738        int ww, hh;
739        ww = (myo->o->align() & FL_ALIGN_WRAP) ? myo->o->w() : 0;
740        hh = myo->o->labelsize();
741        myo->o->measure_label(ww, hh);
742        if (myo->o->align() & FL_ALIGN_TOP) y -= hh;
743        else if (myo->o->align() & FL_ALIGN_BOTTOM) t += hh;
744        else if (myo->o->align() & FL_ALIGN_LEFT) x -= ww + 4;
745        else if (myo->o->align() & FL_ALIGN_RIGHT) r += ww + 4;
746      }
747      if (x < mybx) mybx = x;
748      if (y < myby) myby = y;
749      if (r > mybr) mybr = r;
750      if (t > mybt) mybt = t;
751    }
752  if (selected) return;
753
754  if (show_guides && drag) {
755    // draw overlays for UI Guideline distances
756    // - check for distance to the window edge
757    //    * FLTK suggests 10 pixels from the edge
758    int d;
759    int xsp, ysp;
760    int mybx_bak = mybx, myby_bak = myby, mybr_bak = mybr, mybt_bak = mybt;
761    Fl_Widget_Type *mysel = (Fl_Widget_Type *)selection;
762
763
764    ideal_spacing(xsp, ysp);
765
766    if (drag) {
767      // Check top spacing...
768      if (abs(d = myby - ysp) < 3) {
769        dy -= d;
770        if (drag & DRAG) mybt -= d;
771        myby -= d;
772        draw_v_arrow(mybx+5, myby, 0);
773      }
774
775      // Check bottom spacing...
776      if (abs(d = o->h() - mybt - ysp) < 3) {
777        dy += d;
778        if (drag & DRAG) myby += d;
779        mybt += d;
780        draw_v_arrow(mybx+5, mybt, o->h());
781      }
782
783      // Check left spacing...
784      if (abs(d = mybx - xsp) < 3) {
785        dx -= d;
786        if (drag & DRAG) mybr -= d;
787        mybx -= d;
788        draw_h_arrow(mybx, myby+5, 0);
789      }
790
791      // Check right spacing...
792      if (abs(d = o->w() - mybr - xsp) < 3) {
793        dx += d;
794        if (drag & DRAG) mybx += d;
795        mybr += d;
796        draw_h_arrow(mybr, myby+5, o->w());
797      }
798    }
799
800    if (numselected==1 && selection && !(drag & DRAG)) {
801      // Check ideal sizes
802      int x,y,r,t;
803      newposition(mysel,x,y,r,t);
804      int w = r-x;
805      int h = t-y;
806      int iw = w, ih = h;
807
808      mysel->ideal_size(iw, ih);
809
810      if (drag & (TOP | BOTTOM)) {
811        // Check height
812        if (abs(d = ih - h) < 5) {
813          // Resize height
814          if (drag & TOP) {
815            myby -= d;
816            y -= d;
817            dy -= d;
818          } else {
819            mybt += d;
820            t += d;
821            dy += d;
822          }
823        }
824
825        // Draw height guide
826        draw_height(x < 50 ? x+10 : x-10, y, t,
827                    x < 50 ? FL_ALIGN_RIGHT : FL_ALIGN_LEFT);
828      }
829
830      if (drag & (LEFT | RIGHT)) {
831        // Check width
832        if (abs(d = iw - w) < 5) {
833          // Resize width
834          if (drag & LEFT) {
835            mybx -= d;
836            x -= d;
837            dx -= d;
838          } else {
839            mybr += d;
840            r += d;
841            dx += d;
842          }
843        }
844
845        // Draw width guide
846        draw_width(x, y < 50 ? y+10 : y-10, r,
847                   y < 50 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP);
848      }
849    }
850
851    // Check spacing and alignment between individual widgets
852    if (drag && selection->is_widget()) {
853      for (Fl_Type *q=next; q && q->level>level; q = q->next)
854        if (q != selection && q->is_widget()) {
855          Fl_Widget_Type *qw = (Fl_Widget_Type*)q;
856          // Only check visible widgets...
857          if (!qw->o->visible_r()) continue;
858
859          // Get bounding box of widget...
860          int qx = qw->o->x();
861          int qr = qw->o->x() + qw->o->w();
862          int qy = qw->o->y();
863          int qt = qw->o->y() + qw->o->h();
864
865          if (!(qw->o->align() & FL_ALIGN_INSIDE)) {
866            // Adjust top/bottom for top/bottom labels...
867            int ww, hh;
868            ww = qw->o->w();
869            hh = qw->o->labelsize();
870            qw->o->measure_label(ww, hh);
871            if (qw->o->align() & FL_ALIGN_TOP) qy -= hh;
872            if (qw->o->align() & FL_ALIGN_BOTTOM) qt += hh;
873          }
874
875          // Do horizontal alignment when the widget is within 25
876          // pixels vertically...
877          if (fl_min(abs(qy - mysel->o->y() - mysel->o->h()),
878                     abs(mysel->o->y() - qt)) < 25) {
879            // Align to left of other widget...
880            if ((drag & (LEFT | DRAG)) && abs(d = mybx - qx) < 3) {
881              dx += d;
882              mybx += d;
883              if (drag & DRAG) mybr += d;
884
885              draw_left_brace(qw->o);
886            }
887
888            // Align to right of other widget...
889            if ((drag & (RIGHT | DRAG)) &&
890                abs(d = qr - mybr) < 3) {
891              dx += d;
892              if (drag & DRAG) mybx += d;
893              mybr += d;
894
895              draw_right_brace(qw->o);
896            }
897          }
898
899          // Align to top of other widget...
900          if ((drag & (TOP | DRAG)) && abs(d = myby - qy) < 3) {
901            dy += d;
902            myby += d;
903            if (drag & DRAG) mybt += d;
904
905            draw_top_brace(qw->o);
906          }
907
908          // Align to bottom of other widget...
909          if ((drag & (BOTTOM | DRAG)) && abs(d = qt - mybt) < 3) {
910            dy += d;
911            if (drag & DRAG) myby += d;
912            mybt += d;
913
914            draw_bottom_brace(qw->o);
915          }
916
917          // Check spacing between widgets
918          if (mysel->is_group()) mysel->ideal_spacing(xsp, ysp);
919          else qw->ideal_spacing(xsp, ysp);
920
921          if ((qt)>=myby && qy<=mybt) {
922            if (drag & (LEFT | DRAG)) {
923              // Compare left of selected to left of current
924              if (abs(d = qx - mybx - xsp) >= 3)
925                d = qx - mybx + xsp;
926
927              if (abs(d) < 3) {
928                dx += d;
929                mybx += d;
930                if (drag & DRAG) mybr += d;
931
932                // Draw left arrow
933                draw_h_arrow(mybx, (myby+mybt)/2, qx);
934              }
935
936              // Compare left of selected to right of current
937              if (abs(d = qr - mybx - xsp) >= 3)
938                d = qr - mybx + xsp;
939
940              if (abs(d) < 3) {
941                dx += d;
942                mybx += d;
943                if (drag & DRAG) mybr += d;
944
945                // Draw left arrow
946                draw_h_arrow(mybx, (myby+mybt)/2, qr);
947              }
948            }
949
950            if (drag & (RIGHT | DRAG)) {
951              // Compare right of selected to left of current
952              if (abs(d = qx - mybr - xsp) >= 3)
953                d = qx - mybr + xsp;
954
955              if (abs(d) < 3) {
956                dx += d;
957                if (drag & DRAG) mybx += d;
958                mybr += d;
959
960                // Draw right arrow
961                draw_h_arrow(mybr, (myby+mybt)/2, qx);
962              }
963
964              // Compare right of selected to right of current
965              if (abs(d = qr - mybr + xsp) >= 3)
966                d = qr - mybr - xsp;
967
968              if (abs(d) < 3) {
969                dx += d;
970                if (drag & DRAG) mybx += d;
971                mybr += d;
972
973                // Draw right arrow
974                draw_h_arrow(mybr, (myby+mybt)/2, qr);
975              }
976            }
977          }
978
979          if (qr>=mybx && qx<=mybr) {
980            // Compare top of selected to top of current
981            if (drag & (TOP | DRAG)) {
982              if (abs(d = qy - myby - ysp) >= 3)
983                d = qy - myby + ysp;
984
985              if (abs(d) < 3) {
986                dy += d;
987                myby += d;
988                if (drag & DRAG) mybt += d;
989
990                // Draw up arrow...
991                draw_v_arrow((mybx+mybr)/2, myby, qy);
992              }
993
994              // Compare top of selected to bottom of current
995              if (abs(d = qt - myby - ysp) >= 3)
996                d = qt - myby + ysp;
997
998              if (abs(d) < 3) {
999                dy += d;
1000                myby += d;
1001                if (drag & DRAG) mybt += d;
1002
1003                // Draw up arrow...
1004                draw_v_arrow((mybx+mybr)/2, myby, qt);
1005              }
1006            }
1007
1008            // Compare bottom of selected to top of current
1009            if (drag & (BOTTOM | DRAG)) {
1010              if (abs(d = qy - mybt - ysp) >= 3)
1011                d = qy - mybt + ysp;
1012
1013              if (abs(d) < 3) {
1014                dy += d;
1015                if (drag & DRAG) myby += d;
1016                mybt += d;
1017
1018                // Draw down arrow...
1019                draw_v_arrow((mybx+mybr)/2, mybt, qy);
1020              }
1021
1022              // Compare bottom of selected to bottom of current
1023              if (abs(d = qt - mybt - ysp) >= 3)
1024                d = qt - mybt + ysp;
1025
1026              if (abs(d) < 3) {
1027                dy += d;
1028                if (drag & DRAG) myby += d;
1029                mybt += d;
1030
1031                // Draw down arrow...
1032                draw_v_arrow((mybx+mybr)/2, mybt, qt);
1033              }
1034            }
1035          }
1036        }
1037    }
1038    mysx += mybx-mybx_bak; mysr += mybr-mybr_bak;
1039    mysy += myby-myby_bak; myst += mybt-mybt_bak;
1040  }
1041  // align the snapping selection box with the box we draw.
1042  sx = mysx; sy = mysy; sr = mysr; st = myst;
1043
1044  // Draw selection box + resize handles...
1045  // draw box including all labels
1046  fl_line_style(FL_DOT);
1047  fl_rect(mybx,myby,mybr-mybx,mybt-myby);
1048  fl_line_style(FL_SOLID);
1049  // draw box excluding labels
1050  fl_rect(mysx,mysy,mysr-mysx,myst-mysy);
1051  fl_rectf(mysx,mysy,5,5);
1052  fl_rectf(mysr-5,mysy,5,5);
1053  fl_rectf(mysr-5,myst-5,5,5);
1054  fl_rectf(mysx,myst-5,5,5);
1055}
1056
1057extern Fl_Menu_Item Main_Menu[];
1058
1059// Calculate new bounding box of selected widgets:
1060void Fl_Window_Type::fix_overlay() {
1061  Main_Menu[40].label("Hide O&verlays");
1062  overlays_invisible = 0;
1063  recalc = 1;
1064  ((Overlay_Window *)(this->o))->redraw_overlay();
1065}
1066
1067// do that for every window (when selected set changes):
1068void redraw_overlays() {
1069  for (Fl_Type *o=Fl_Type::first; o; o=o->next)
1070    if (o->is_window()) ((Fl_Window_Type*)o)->fix_overlay();
1071}
1072
1073void toggle_overlays(Fl_Widget *,void *) {
1074  overlays_invisible = !overlays_invisible;
1075
1076  if (overlays_invisible) Main_Menu[40].label("Show O&verlays");
1077  else Main_Menu[40].label("Hide O&verlays");
1078
1079  for (Fl_Type *o=Fl_Type::first; o; o=o->next)
1080    if (o->is_window()) {
1081      Fl_Widget_Type* w = (Fl_Widget_Type*)o;
1082      ((Overlay_Window*)(w->o))->redraw_overlay();
1083    }
1084}
1085
1086extern void select(Fl_Type *,int);
1087extern void select_only(Fl_Type *);
1088extern void deselect();
1089extern Fl_Type* in_this_only;
1090extern void fix_group_size(Fl_Type *t);
1091
1092extern Fl_Menu_Item Main_Menu[];
1093extern Fl_Menu_Item New_Menu[];
1094
1095// move the selected children according to current dx,dy,drag state:
1096void Fl_Window_Type::moveallchildren()
1097{
1098  undo_checkpoint();
1099  Fl_Type *i;
1100  for (i=next; i && i->level>level;) {
1101    if (i->selected && i->is_widget() && !i->is_menu_item()) {
1102      Fl_Widget_Type* myo = (Fl_Widget_Type*)i;
1103      int x,y,r,t;
1104      newposition(myo,x,y,r,t);
1105      myo->o->resize(x,y,r-x,t-y);
1106      // move all the children, whether selected or not:
1107      Fl_Type* p;
1108      for (p = myo->next; p && p->level>myo->level; p = p->next)
1109        if (p->is_widget() && !p->is_menu_item()) {
1110          Fl_Widget_Type* myo2 = (Fl_Widget_Type*)p;
1111          int X,Y,R,T;
1112          newposition(myo2,X,Y,R,T);
1113          myo2->o->resize(X,Y,R-X,T-Y);
1114        }
1115      i = p;
1116    } else {
1117      i = i->next;
1118    }
1119  }
1120  for (i=next; i && i->level>level; i=i->next)
1121    fix_group_size(i);
1122  o->redraw();
1123  recalc = 1;
1124  ((Overlay_Window *)(this->o))->redraw_overlay();
1125  set_modflag(1);
1126  dx = dy = 0;
1127
1128  update_xywh();
1129}
1130
1131int Fl_Window_Type::handle(int event) {
1132  static Fl_Type* selection;
1133  switch (event) {
1134  case FL_PUSH:
1135    x1 = mx = Fl::event_x();
1136    y1 = my = Fl::event_y();
1137    drag = dx = dy = 0;
1138    // test for popup menu:
1139    if (Fl::event_button() >= 3) {
1140      in_this_only = this; // modifies how some menu items work.
1141      static const Fl_Menu_Item* myprev;
1142      const Fl_Menu_Item* m = New_Menu->popup(mx,my,"New",myprev);
1143      if (m && m->callback()) {myprev = m; m->do_callback(this->o);}
1144      in_this_only = 0;
1145      return 1;
1146    }
1147    // find the innermost item clicked on:
1148    selection = this;
1149    {for (Fl_Type* i=next; i && i->level>level; i=i->next)
1150      if (i->is_widget() && !i->is_menu_item()) {
1151      Fl_Widget_Type* myo = (Fl_Widget_Type*)i;
1152      for (Fl_Widget *o1 = myo->o; o1; o1 = o1->parent())
1153        if (!o1->visible()) goto CONTINUE2;
1154      if (Fl::event_inside(myo->o)) {
1155        selection = myo;
1156        if (Fl::event_clicks()==1)
1157          reveal_in_browser(myo);
1158      }
1159    CONTINUE2:;
1160    }}
1161    // see if user grabs edges of selected region:
1162    if (numselected && !(Fl::event_state(FL_SHIFT)) &&
1163        mx<=br+snap && mx>=bx-snap && my<=bt+snap && my>=by-snap) {
1164      int snap1 = snap>5 ? snap : 5;
1165      int w1 = (br-bx)/4; if (w1 > snap1) w1 = snap1;
1166      if (mx>=br-w1) drag |= RIGHT;
1167      else if (mx<bx+w1) drag |= LEFT;
1168      w1 = (bt-by)/4; if (w1 > snap1) w1 = snap1;
1169      if (my<=by+w1) drag |= TOP;
1170      else if (my>bt-w1) drag |= BOTTOM;
1171      if (!drag) drag = DRAG;
1172    }
1173    // do object-specific selection of other objects:
1174    {Fl_Type* t = selection->click_test(mx, my);
1175    if (t) {
1176      //if (t == selection) return 1; // indicates mouse eaten w/o change
1177      if (Fl::event_state(FL_SHIFT)) {
1178        Fl::event_is_click(0);
1179        select(t, !t->selected);
1180      } else {
1181        deselect();
1182        select(t, 1);
1183        if (t->is_menu_item()) t->open();
1184      }
1185      selection = t;
1186      drag = 0;
1187    } else {
1188      if (!drag) drag = BOX; // if all else fails, start a new selection region
1189    }}
1190    return 1;
1191
1192  case FL_DRAG:
1193    if (!drag) return 0;
1194    mx = Fl::event_x();
1195    my = Fl::event_y();
1196    newdx();
1197    return 1;
1198
1199  case FL_RELEASE:
1200    if (!drag) return 0;
1201    mx = Fl::event_x();
1202    my = Fl::event_y();
1203    if (drag != BOX && (dx || dy || !Fl::event_is_click())) {
1204      if (dx || dy) moveallchildren();
1205    } else if ((Fl::event_clicks() || Fl::event_state(FL_CTRL))) {
1206      Fl_Widget_Type::open();
1207    } else {
1208      if (mx<x1) {int t = x1; x1 = mx; mx = t;}
1209      if (my<y1) {int t = y1; y1 = my; my = t;}
1210      int n = 0;
1211      int toggle = Fl::event_state(FL_SHIFT);
1212      // clear selection on everything:
1213      if (!toggle) deselect(); else Fl::event_is_click(0);
1214      // select everything in box:
1215      for (Fl_Type*i=next; i&&i->level>level; i=i->next)
1216        if (i->is_widget() && !i->is_menu_item()) {
1217        Fl_Widget_Type* myo = (Fl_Widget_Type*)i;
1218        for (Fl_Widget *o1 = myo->o; o1; o1 = o1->parent())
1219          if (!o1->visible()) goto CONTINUE;
1220        if (Fl::event_inside(myo->o)) selection = myo;
1221        if (myo->o->x()>=x1 && myo->o->y()>y1 &&
1222            myo->o->x()+myo->o->w()<mx && myo->o->y()+myo->o->h()<my) {
1223          n++;
1224          select(myo, toggle ? !myo->selected : 1);
1225        }
1226      CONTINUE:;
1227      }
1228      // if nothing in box, select what was clicked on:
1229      if (!n) {
1230        select(selection, toggle ? !selection->selected : 1);
1231      }
1232    }
1233    drag = 0;
1234    ((Overlay_Window *)o)->redraw_overlay();
1235    return 1;
1236
1237  case FL_KEYBOARD: {
1238
1239    int backtab = 0;
1240    switch (Fl::event_key()) {
1241
1242    case FL_Escape:
1243      ((Fl_Window*)o)->hide();
1244      return 1;
1245
1246    case 0xFE20: // backtab
1247      backtab = 1;
1248    case FL_Tab: {
1249      if (Fl::event_state(FL_SHIFT)) backtab = 1;
1250      // find current child:
1251      Fl_Type *i = Fl_Type::current;
1252      while (i && (!i->is_widget() || i->is_menu_item())) i = i->parent;
1253      if (!i) return 0;
1254      Fl_Type *p = i->parent;
1255      while (p && p != this) p = p->parent;
1256      if (!p || !p->is_widget()) {
1257        i = next; if (!i || i->level <= level) return 0;
1258      }
1259      p = i;
1260      for (;;) {
1261        i = backtab ? i->prev : i->next;
1262        if (!i || i->level <= level) {i = p; break;}
1263        if (i->is_widget() && !i->is_menu_item()) break;
1264      }
1265      deselect(); select(i,1);
1266      return 1;}
1267
1268    case FL_Left:  dx = -1; dy = 0; goto ARROW;
1269    case FL_Right: dx = +1; dy = 0; goto ARROW;
1270    case FL_Up:    dx = 0; dy = -1; goto ARROW;
1271    case FL_Down:  dx = 0; dy = +1; goto ARROW;
1272    ARROW:
1273      // for some reason BOTTOM/TOP are swapped... should be fixed...
1274      drag = (Fl::event_state(FL_SHIFT)) ? (RIGHT|TOP) : DRAG;
1275      if (Fl::event_state(FL_CTRL)) {dx *= gridx; dy *= gridy;}
1276      moveallchildren();
1277      drag = 0;
1278      return 1;
1279
1280    case 'o':
1281      toggle_overlays(0, 0);
1282      break;
1283
1284    default:
1285      return 0;
1286    }}
1287
1288  case FL_SHORTCUT: {
1289    in_this_only = this; // modifies how some menu items work.
1290    const Fl_Menu_Item* m = Main_Menu->test_shortcut();
1291    if (m && m->callback()) m->do_callback(this->o);
1292    in_this_only = 0;
1293    return (m != 0);}
1294
1295  default:
1296    return 0;
1297  }
1298}
1299
1300////////////////////////////////////////////////////////////////
1301
1302#include <stdio.h>
1303#include "../src/flstring.h"
1304
1305void Fl_Window_Type::write_code1() {
1306  Fl_Widget_Type::write_code1();
1307}
1308
1309void Fl_Window_Type::write_code2() {
1310  const char *var = is_class() ? "this" : name() ? name() : "o";
1311  write_extra_code();
1312  if (modal) write_c("%s%s->set_modal();\n", indent(), var);
1313  else if (non_modal) write_c("%s%s->set_non_modal();\n", indent(), var);
1314  if (!((Fl_Window*)o)->border()) {
1315    write_c("%s%s->clear_border();\n", indent(), var);
1316  }
1317  if (xclass) {
1318    write_c("%s%s->xclass(", indent(), var);
1319    write_cstring(xclass);
1320    write_c(");\n");
1321  }
1322  if (sr_max_w || sr_max_h) {
1323    write_c("%s%s->size_range(%d, %d, %d, %d);\n", indent(), var,
1324            sr_min_w, sr_min_h, sr_max_w, sr_max_h);
1325  } else if (sr_min_w || sr_min_h) {
1326    write_c("%s%s->size_range(%d, %d);\n", indent(), var, sr_min_w, sr_min_h);
1327  }
1328  write_c("%s%s->end();\n", indent(), var);
1329  if (((Fl_Window*)o)->resizable() == o)
1330    write_c("%s%s->resizable(%s);\n", indent(), var, var);
1331  write_block_close();
1332}
1333
1334void Fl_Window_Type::write_properties() {
1335  Fl_Widget_Type::write_properties();
1336  if (modal) write_string("modal");
1337  else if (non_modal) write_string("non_modal");
1338  if (!((Fl_Window*)o)->border()) write_string("noborder");
1339  if (xclass) {write_string("xclass"); write_word(xclass);}
1340  if (sr_min_w || sr_min_h || sr_max_w || sr_max_h)
1341    write_string("size_range {%d %d %d %d}", sr_min_w, sr_min_h, sr_max_w, sr_max_h);
1342  if (o->visible()) write_string("visible");
1343}
1344
1345extern int pasteoffset;
1346void Fl_Window_Type::read_property(const char *c) {
1347  if (!strcmp(c,"modal")) {
1348    modal = 1;
1349  } else if (!strcmp(c,"non_modal")) {
1350    non_modal = 1;
1351  } else if (!strcmp(c, "visible")) {
1352    if (Fl::first_window()) open(); // only if we are using user interface
1353  } else if (!strcmp(c,"noborder")) {
1354    ((Fl_Window*)o)->border(0);
1355  } else if (!strcmp(c,"xclass")) {
1356    storestring(read_word(),xclass);
1357    ((Fl_Window*)o)->xclass(xclass);
1358  } else if (!strcmp(c,"size_range")) {
1359    int mw, mh, MW, MH;
1360    if (sscanf(read_word(),"%d %d %d %d",&mw,&mh,&MW,&MH) == 4) {
1361      sr_min_w = mw; sr_min_h = mh; sr_max_w = MW; sr_max_h = MH;
1362    }
1363  } else if (!strcmp(c,"xywh")) {
1364    Fl_Widget_Type::read_property(c);
1365    pasteoffset = 0; // make it not apply to contents
1366  } else {
1367    Fl_Widget_Type::read_property(c);
1368  }
1369}
1370
1371int Fl_Window_Type::read_fdesign(const char* propname, const char* value) {
1372  int x;
1373  o->box(FL_NO_BOX); // because fdesign always puts an Fl_Box next
1374  if (!strcmp(propname,"Width")) {
1375    if (sscanf(value,"%d",&x) == 1) o->size(x,o->h());
1376  } else if (!strcmp(propname,"Height")) {
1377    if (sscanf(value,"%d",&x) == 1) o->size(o->w(),x);
1378  } else if (!strcmp(propname,"NumberofWidgets")) {
1379    return 1; // we can figure out count from file
1380  } else if (!strcmp(propname,"border")) {
1381    if (sscanf(value,"%d",&x) == 1) ((Fl_Window*)o)->border(x);
1382  } else if (!strcmp(propname,"title")) {
1383    label(value);
1384  } else {
1385    return Fl_Widget_Type::read_fdesign(propname,value);
1386  }
1387  return 1;
1388}
1389
1390///////////////////////////////////////////////////////////////////////
1391
1392Fl_Widget_Class_Type Fl_Widget_Class_type;
1393Fl_Widget_Class_Type *current_widget_class = 0;
1394
1395Fl_Type *Fl_Widget_Class_Type::make() {
1396  Fl_Type *p = Fl_Type::current;
1397  while (p && (!p->is_decl_block() || (p->is_widget() && p->is_class()))) p = p->parent;
1398  Fl_Widget_Class_Type *myo = new Fl_Widget_Class_Type();
1399  myo->name("UserInterface");
1400
1401  if (!this->o) {// template widget
1402    this->o = new Fl_Window(100,100);
1403    Fl_Group::current(0);
1404  }
1405  // Set the size ranges for this window; in order to avoid opening the
1406  // X display we use an arbitrary maximum size...
1407  ((Fl_Window *)(this->o))->size_range(gridx, gridy,
1408                                       3072, 2048,
1409                                       gridx, gridy, 0);
1410  myo->factory = this;
1411  myo->drag = 0;
1412  myo->numselected = 0;
1413  Overlay_Window *w = new Overlay_Window(100,100);
1414  w->window = myo;
1415  myo->o = w;
1416  myo->add(p);
1417  myo->modal = 0;
1418  myo->non_modal = 0;
1419  myo->wc_relative = 0;
1420
1421  return myo;
1422}
1423
1424void Fl_Widget_Class_Type::write_properties() {
1425  Fl_Window_Type::write_properties();
1426  if (wc_relative) write_string("position_relative");
1427}
1428
1429void Fl_Widget_Class_Type::read_property(const char *c) {
1430  if (!strcmp(c,"position_relative")) {
1431    wc_relative = 1;
1432  } else {
1433    Fl_Window_Type::read_property(c);
1434  }
1435}
1436
1437void Fl_Widget_Class_Type::write_code1() {
1438#if 0
1439  Fl_Widget_Type::write_code1();
1440#endif // 0
1441
1442  current_widget_class = this;
1443  write_public_state = 1;
1444
1445  const char *c = subclass();
1446  if (!c) c = "Fl_Group";
1447
1448  write_h("\nclass %s : public %s {\n", name(), c);
1449  if (strstr(c, "Window")) {
1450    write_h("  void _%s();\n", name());
1451    write_h("public:\n");
1452    write_h("  %s(int X, int Y, int W, int H, const char *L = 0);\n", name());
1453    write_h("  %s(int W, int H, const char *L = 0);\n", name());
1454
1455    write_c("%s::%s(int X, int Y, int W, int H, const char *L)\n", name(), name());
1456    write_c("  : %s(X, Y, W, H, L) {\n", c);
1457    write_c("  _%s();\n", name());
1458    write_c("}\n\n");
1459
1460    write_c("%s::%s(int W, int H, const char *L)\n", name(), name());
1461    write_c("  : %s(0, 0, W, H, L) {\n", c);
1462    write_c("  clear_flag(16);\n");
1463    write_c("  _%s();\n", name());
1464    write_c("}\n\n");
1465
1466    write_c("void %s::_%s() {\n", name(), name());
1467//    write_c("  %s *w = this;\n", name());
1468  } else {
1469    write_h("public:\n");
1470    write_h("  %s(int X, int Y, int W, int H, const char *L = 0);\n", name());
1471
1472    write_c("%s::%s(int X, int Y, int W, int H, const char *L)\n", name(), name());
1473    if (wc_relative)
1474      write_c("  : %s(0, 0, W, H, L) {\n", c);
1475    else
1476      write_c("  : %s(X, Y, W, H, L) {\n", c);
1477  }
1478
1479//  write_c("  %s *o = this;\n", name());
1480
1481  write_widget_code();
1482}
1483
1484void Fl_Widget_Class_Type::write_code2() {
1485  write_extra_code();
1486  if (wc_relative) write_c("%sposition(X, Y);\n", indent());
1487  if (modal) write_c("%sset_modal();\n", indent());
1488  else if (non_modal) write_c("%sset_non_modal();\n", indent());
1489  if (!((Fl_Window*)o)->border()) write_c("%sclear_border();\n", indent());
1490  if (xclass) {
1491    write_c("%sxclass(", indent());
1492    write_cstring(xclass);
1493    write_c(");\n");
1494  }
1495  write_c("%send();\n", indent());
1496  if (((Fl_Window*)o)->resizable() == o)
1497    write_c("%sresizable(this);\n", indent());
1498  write_c("}\n");
1499}
1500
1501////////////////////////////////////////////////////////////////
1502// live mode support
1503
1504Fl_Widget *Fl_Window_Type::enter_live_mode(int) {
1505  Fl_Window *win = new Fl_Window(o->x(), o->y(), o->w(), o->h());
1506  live_widget = win;
1507  if (live_widget) {
1508    copy_properties();
1509    Fl_Type *n;
1510    for (n = next; n && n->level > level; n = n->next) {
1511      if (n->level == level+1)
1512        n->enter_live_mode();
1513    }
1514    win->end();
1515  }
1516  return live_widget;
1517}
1518
1519void Fl_Window_Type::leave_live_mode() {
1520}
1521
1522/**
1523 * copy all properties from the edit widget to the live widget
1524 */
1525void Fl_Window_Type::copy_properties() {
1526  Fl_Widget_Type::copy_properties();
1527  /// \todo copy resizing constraints over
1528}
1529
1530
1531//
1532// End of "$Id$".
1533//
Note: See TracBrowser for help on using the repository browser.