|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: Fl_Window_Type.cxx 8089 2010-12-20 22:19:24Z matt $" 00003 // 00004 // Window type code for the Fast Light Tool Kit (FLTK). 00005 // 00006 // The widget describing an Fl_Window. This is also all the code 00007 // for interacting with the overlay, which allows the user to 00008 // select, move, and resize the children widgets. 00009 // 00010 // Copyright 1998-2010 by Bill Spitzak and others. 00011 // 00012 // This library is free software; you can redistribute it and/or 00013 // modify it under the terms of the GNU Library General Public 00014 // License as published by the Free Software Foundation; either 00015 // version 2 of the License, or (at your option) any later version. 00016 // 00017 // This library is distributed in the hope that it will be useful, 00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00020 // Library General Public License for more details. 00021 // 00022 // You should have received a copy of the GNU Library General Public 00023 // License along with this library; if not, write to the Free Software 00024 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00025 // USA. 00026 // 00027 // Please report all bugs and problems on the following page: 00028 // 00029 // http://www.fltk.org/str.php 00030 // 00031 00032 #include <FL/Fl.H> 00033 #include <FL/Fl_Overlay_Window.H> 00034 #include <FL/fl_message.H> 00035 #include <FL/fl_draw.H> 00036 #include <FL/x.H> 00037 #include <FL/Fl_Menu_Item.H> 00038 #include <FL/Fl_Round_Button.H> 00039 #include "Fl_Widget_Type.h" 00040 #include "undo.h" 00041 #include <math.h> 00042 #include <stdlib.h> 00043 #include "alignment_panel.h" 00044 #include <stdio.h> 00045 00046 extern int gridx; 00047 extern int gridy; 00048 extern int snap; 00049 extern int show_guides; 00050 00051 int include_H_from_C = 1; 00052 int use_FL_COMMAND = 0; 00053 extern int i18n_type; 00054 extern const char* i18n_include; 00055 extern const char* i18n_function; 00056 extern const char* i18n_file; 00057 extern const char* i18n_set; 00058 00059 extern Fl_Preferences fluid_prefs; 00060 00061 inline int fl_min(int a, int b) { return (a < b ? a : b); } 00062 00063 #include "widget_panel.h" 00064 00065 // Update the XYWH values in the widget panel... 00066 static void update_xywh() { 00067 if (current_widget && current_widget->is_widget()) { 00068 widget_x_input->value(((Fl_Widget_Type *)current_widget)->o->x()); 00069 widget_y_input->value(((Fl_Widget_Type *)current_widget)->o->y()); 00070 widget_w_input->value(((Fl_Widget_Type *)current_widget)->o->w()); 00071 widget_h_input->value(((Fl_Widget_Type *)current_widget)->o->h()); 00072 } 00073 } 00074 00075 void guides_cb(Fl_Check_Button *i, long) { 00076 show_guides = i->value(); 00077 fluid_prefs.set("show_guides", show_guides); 00078 00079 for (Fl_Type *p = Fl_Type::first; p; p = p->next) { 00080 if (p->is_window()) { 00081 Fl_Window_Type *w = (Fl_Window_Type *)p; 00082 ((Fl_Overlay_Window *)(w->o))->redraw_overlay(); 00083 } 00084 } 00085 } 00086 00087 void grid_cb(Fl_Int_Input *i, long v) { 00088 int n = atoi(i->value()); 00089 if (n < 0) n = 0; 00090 switch (v) { 00091 case 1: 00092 gridx = n; 00093 fluid_prefs.set("gridx", n); 00094 break; 00095 case 2: 00096 gridy = n; 00097 fluid_prefs.set("gridy", n); 00098 break; 00099 case 3: 00100 snap = n; 00101 fluid_prefs.set("snap", n); 00102 break; 00103 } 00104 00105 // Next go through all of the windows in the project and set the 00106 // stepping for resizes... 00107 Fl_Type *p; 00108 Fl_Window_Type *w; 00109 00110 for (p = Fl_Type::first; p; p = p->next) { 00111 if (p->is_window()) { 00112 w = (Fl_Window_Type *)p; 00113 ((Fl_Window *)(w->o))->size_range(gridx, gridy, 00114 Fl::w(), Fl::h(), 00115 gridx, gridy, 0); 00116 } 00117 } 00118 } 00119 00120 // Set default widget sizes... 00121 void default_widget_size_cb(Fl_Round_Button *b, long size) { 00122 // Update the "normal" text size of new widgets... 00123 b->setonly(); 00124 Fl_Widget_Type::default_size = size; 00125 fluid_prefs.set("widget_size", Fl_Widget_Type::default_size); 00126 } 00127 00128 00129 void i18n_type_cb(Fl_Choice *c, void *) { 00130 undo_checkpoint(); 00131 00132 switch (i18n_type = c->value()) { 00133 case 0 : /* None */ 00134 i18n_include_input->hide(); 00135 i18n_file_input->hide(); 00136 i18n_set_input->hide(); 00137 i18n_function_input->hide(); 00138 break; 00139 case 1 : /* GNU gettext */ 00140 i18n_include_input->value("<libintl.h>"); 00141 i18n_include = i18n_include_input->value(); 00142 i18n_function_input->value("gettext"); 00143 i18n_function = i18n_function_input->value(); 00144 i18n_include_input->show(); 00145 i18n_file_input->hide(); 00146 i18n_set_input->hide(); 00147 i18n_function_input->show(); 00148 break; 00149 case 2 : /* POSIX cat */ 00150 i18n_include_input->value("<nl_types.h>"); 00151 i18n_file_input->value(""); 00152 i18n_file = i18n_file_input->value(); 00153 i18n_set_input->value("1"); 00154 i18n_set = i18n_set_input->value(); 00155 i18n_include_input->show(); 00156 i18n_include = i18n_include_input->value(); 00157 i18n_file_input->show(); 00158 i18n_set_input->show(); 00159 i18n_function_input->hide(); 00160 break; 00161 } 00162 00163 set_modflag(1); 00164 } 00165 00166 void i18n_text_cb(Fl_Input *i, void *) { 00167 undo_checkpoint(); 00168 00169 if (i == i18n_function_input) 00170 i18n_function = i->value(); 00171 else if (i == i18n_file_input) 00172 i18n_file = i->value(); 00173 else if (i == i18n_include_input) 00174 i18n_include = i->value(); 00175 00176 set_modflag(1); 00177 } 00178 00179 void i18n_int_cb(Fl_Int_Input *i, void *) { 00180 undo_checkpoint(); 00181 00182 if (i == i18n_set_input) 00183 i18n_set = i->value(); 00184 00185 set_modflag(1); 00186 } 00187 00188 extern const char* header_file_name; 00189 extern const char* code_file_name; 00190 00191 void show_project_cb(Fl_Widget *, void *) { 00192 if(project_window==0) make_project_window(); 00193 include_H_from_C_button->value(include_H_from_C); 00194 use_FL_COMMAND_button->value(use_FL_COMMAND); 00195 header_file_input->value(header_file_name); 00196 code_file_input->value(code_file_name); 00197 i18n_type_chooser->value(i18n_type); 00198 i18n_function_input->value(i18n_function); 00199 i18n_file_input->value(i18n_file); 00200 i18n_set_input->value(i18n_set); 00201 i18n_include_input->value(i18n_include); 00202 switch (i18n_type) { 00203 case 0 : /* None */ 00204 i18n_include_input->hide(); 00205 i18n_file_input->hide(); 00206 i18n_set_input->hide(); 00207 i18n_function_input->hide(); 00208 break; 00209 case 1 : /* GNU gettext */ 00210 i18n_include_input->show(); 00211 i18n_file_input->hide(); 00212 i18n_set_input->hide(); 00213 i18n_function_input->show(); 00214 break; 00215 case 2 : /* POSIX cat */ 00216 i18n_include_input->show(); 00217 i18n_file_input->show(); 00218 i18n_set_input->show(); 00219 i18n_function_input->hide(); 00220 break; 00221 } 00222 project_window->hotspot(project_window); 00223 project_window->show(); 00224 } 00225 00226 void show_grid_cb(Fl_Widget *, void *) { 00227 char buf[128]; 00228 sprintf(buf,"%d",gridx); horizontal_input->value(buf); 00229 sprintf(buf,"%d",gridy); vertical_input->value(buf); 00230 sprintf(buf,"%d",snap); snap_input->value(buf); 00231 guides_toggle->value(show_guides); 00232 int s = Fl_Widget_Type::default_size; 00233 if (s<=8) def_widget_size[0]->setonly(); 00234 else if (s<=11) def_widget_size[1]->setonly(); 00235 else if (s<=14) def_widget_size[2]->setonly(); 00236 else if (s<=18) def_widget_size[3]->setonly(); 00237 else if (s<=24) def_widget_size[4]->setonly(); 00238 else if (s<=32) def_widget_size[5]->setonly(); 00239 grid_window->hotspot(grid_window); 00240 grid_window->show(); 00241 } 00242 00243 void show_settings_cb(Fl_Widget *, void *) { 00244 settings_window->hotspot(settings_window); 00245 settings_window->show(); 00246 } 00247 00248 void show_global_settings_cb(Fl_Widget *, void *) { 00249 global_settings_window->hotspot(global_settings_window); 00250 show_global_settings_window(); 00251 } 00252 00253 void header_input_cb(Fl_Input* i, void*) { 00254 if (header_file_name && strcmp(header_file_name, i->value())) 00255 set_modflag(1); 00256 header_file_name = i->value(); 00257 } 00258 void code_input_cb(Fl_Input* i, void*) { 00259 if (code_file_name && strcmp(code_file_name, i->value())) 00260 set_modflag(1); 00261 code_file_name = i->value(); 00262 } 00263 00264 void include_H_from_C_button_cb(Fl_Check_Button* b, void*) { 00265 if (include_H_from_C != b->value()) { 00266 set_modflag(1); 00267 include_H_from_C = b->value(); 00268 } 00269 } 00270 00271 void use_FL_COMMAND_button_cb(Fl_Check_Button* b, void*) { 00272 if (use_FL_COMMAND != b->value()) { 00273 set_modflag(1); 00274 use_FL_COMMAND = b->value(); 00275 } 00276 } 00277 00279 00280 Fl_Menu_Item window_type_menu[] = { 00281 {"Single",0,0,(void*)FL_WINDOW}, 00282 {"Double",0,0,(void*)(FL_WINDOW+1)}, 00283 {0}}; 00284 00285 static int overlays_invisible; 00286 00287 // The following Fl_Widget is used to simulate the windows. It has 00288 // an overlay for the fluid ui, and special-cases the FL_NO_BOX. 00289 00290 class Overlay_Window : public Fl_Overlay_Window { 00291 void draw(); 00292 void draw_overlay(); 00293 public: 00294 Fl_Window_Type *window; 00295 int handle(int); 00296 Overlay_Window(int W,int H) : Fl_Overlay_Window(W,H) {Fl_Group::current(0);} 00297 void resize(int,int,int,int); 00298 uchar *read_image(int &ww, int &hh); 00299 }; 00300 void Overlay_Window::draw() { 00301 const int CHECKSIZE = 8; 00302 // see if box is clear or a frame or rounded: 00303 if ((damage()&FL_DAMAGE_ALL) && 00304 (!box() || (box()>=4&&!(box()&2)) || box()>=_FL_ROUNDED_BOX)) { 00305 // if so, draw checkerboard so user can see what areas are clear: 00306 for (int Y = 0; Y < h(); Y += CHECKSIZE) 00307 for (int X = 0; X < w(); X += CHECKSIZE) { 00308 fl_color(((Y/(2*CHECKSIZE))&1) != ((X/(2*CHECKSIZE))&1) ? 00309 FL_WHITE : FL_BLACK); 00310 fl_rectf(X,Y,CHECKSIZE,CHECKSIZE); 00311 } 00312 } 00313 Fl_Overlay_Window::draw(); 00314 } 00315 00316 extern Fl_Window *main_window; 00317 00318 // Read an image of the overlay window 00319 uchar *Overlay_Window::read_image(int &ww, int &hh) { 00320 // Create an off-screen buffer for the window... 00321 //main_window->make_current(); 00322 make_current(); 00323 00324 ww = w(); 00325 hh = h(); 00326 00327 Fl_Offscreen offscreen = fl_create_offscreen(ww, hh); 00328 uchar *pixels; 00329 00330 // Redraw the window into the offscreen buffer... 00331 fl_begin_offscreen(offscreen); 00332 00333 if (!shown()) image(Fl::scheme_bg_); 00334 00335 redraw(); 00336 draw(); 00337 00338 // Read the screen image... 00339 pixels = fl_read_image(0, 0, 0, ww, hh); 00340 00341 fl_end_offscreen(); 00342 00343 // Cleanup and return... 00344 fl_delete_offscreen(offscreen); 00345 main_window->make_current(); 00346 return pixels; 00347 } 00348 00349 void Overlay_Window::draw_overlay() { 00350 window->draw_overlay(); 00351 } 00352 int Overlay_Window::handle(int e) { 00353 int ret = window->handle(e); 00354 if (ret==0) { 00355 switch (e) { 00356 case FL_SHOW: 00357 case FL_HIDE: 00358 ret = Fl_Overlay_Window::handle(e); 00359 } 00360 } 00361 return ret; 00362 } 00363 00364 Fl_Type *Fl_Window_Type::make() { 00365 Fl_Type *p = Fl_Type::current; 00366 while (p && !p->is_code_block()) p = p->parent; 00367 if (!p) { 00368 fl_message("Please select a function"); 00369 return 0; 00370 } 00371 Fl_Window_Type *myo = new Fl_Window_Type(); 00372 if (!this->o) {// template widget 00373 this->o = new Fl_Window(100,100); 00374 Fl_Group::current(0); 00375 } 00376 // Set the size ranges for this window; in order to avoid opening the 00377 // X display we use an arbitrary maximum size... 00378 ((Fl_Window *)(this->o))->size_range(gridx, gridy, 00379 3072, 2048, 00380 gridx, gridy, 0); 00381 myo->factory = this; 00382 myo->drag = 0; 00383 myo->numselected = 0; 00384 Overlay_Window *w = new Overlay_Window(100,100); 00385 w->window = myo; 00386 myo->o = w; 00387 myo->add(p); 00388 myo->modal = 0; 00389 myo->non_modal = 0; 00390 return myo; 00391 } 00392 00393 void Fl_Window_Type::add_child(Fl_Type* cc, Fl_Type* before) { 00394 if (!cc->is_widget()) return; 00395 Fl_Widget_Type* c = (Fl_Widget_Type*)cc; 00396 Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; 00397 ((Fl_Window*)o)->insert(*(c->o), b); 00398 o->redraw(); 00399 } 00400 00401 void Fl_Window_Type::remove_child(Fl_Type* cc) { 00402 Fl_Widget_Type* c = (Fl_Widget_Type*)cc; 00403 ((Fl_Window*)o)->remove(c->o); 00404 o->redraw(); 00405 } 00406 00407 void Fl_Window_Type::move_child(Fl_Type* cc, Fl_Type* before) { 00408 Fl_Widget_Type* c = (Fl_Widget_Type*)cc; 00409 ((Fl_Window*)o)->remove(c->o); 00410 Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; 00411 ((Fl_Window*)o)->insert(*(c->o), b); 00412 o->redraw(); 00413 } 00414 00416 00417 // Double-click on window widget shows the window, or if already shown, 00418 // it shows the control panel. 00419 void Fl_Window_Type::open() { 00420 Overlay_Window *w = (Overlay_Window *)o; 00421 if (w->shown()) { 00422 w->show(); 00423 Fl_Widget_Type::open(); 00424 } else { 00425 Fl_Widget *p = w->resizable(); 00426 if (!p) w->resizable(w); 00427 w->show(); 00428 w->resizable(p); 00429 } 00430 00431 w->image(Fl::scheme_bg_); 00432 w->size_range(gridx, gridy, Fl::w(), Fl::h(), gridx, gridy, 0); 00433 } 00434 00435 // Read an image of the window 00436 uchar *Fl_Window_Type::read_image(int &ww, int &hh) { 00437 Overlay_Window *w = (Overlay_Window *)o; 00438 00439 // Read the screen image... 00440 return (w->read_image(ww, hh)); 00441 } 00442 00443 00444 // control panel items: 00445 00446 void modal_cb(Fl_Light_Button* i, void* v) { 00447 if (v == LOAD) { 00448 if (!current_widget->is_window()) {i->hide(); return;} 00449 i->show(); 00450 i->value(((Fl_Window_Type *)current_widget)->modal); 00451 } else { 00452 ((Fl_Window_Type *)current_widget)->modal = i->value(); 00453 set_modflag(1); 00454 } 00455 } 00456 00457 void non_modal_cb(Fl_Light_Button* i, void* v) { 00458 if (v == LOAD) { 00459 if (!current_widget->is_window()) {i->hide(); return;} 00460 i->show(); 00461 i->value(((Fl_Window_Type *)current_widget)->non_modal); 00462 } else { 00463 ((Fl_Window_Type *)current_widget)->non_modal = i->value(); 00464 set_modflag(1); 00465 } 00466 } 00467 00468 void border_cb(Fl_Light_Button* i, void* v) { 00469 if (v == LOAD) { 00470 if (!current_widget->is_window()) {i->hide(); return;} 00471 i->show(); 00472 i->value(((Fl_Window*)(current_widget->o))->border()); 00473 } else { 00474 ((Fl_Window*)(current_widget->o))->border(i->value()); 00475 set_modflag(1); 00476 } 00477 } 00478 00479 void xclass_cb(Fl_Input* i, void* v) { 00480 if (v == LOAD) { 00481 if (!current_widget->is_window()) { 00482 i->hide(); 00483 i->parent()->hide(); // hides the "X Class:" label as well 00484 return; 00485 } 00486 i->show(); 00487 i->parent()->show(); 00488 i->value(((Fl_Widget_Type *)current_widget)->xclass); 00489 } else { 00490 int mod = 0; 00491 for (Fl_Type *o = Fl_Type::first; o; o = o->next) { 00492 if (o->selected && o->is_widget()) { 00493 mod = 1; 00494 Fl_Widget_Type* w = (Fl_Widget_Type*)o; 00495 if (w->is_window() || w->is_button()) 00496 storestring(i->value(),w->xclass); 00497 if (w->is_window()) ((Fl_Window*)(w->o))->xclass(w->xclass); 00498 else if (w->is_menu_item()) w->redraw(); 00499 } 00500 } 00501 if (mod) set_modflag(1); 00502 } 00503 } 00504 00506 00507 void Fl_Window_Type::setlabel(const char *n) { 00508 if (o) ((Fl_Window *)o)->label(n); 00509 } 00510 00511 // make() is called on this widget when user picks window off New menu: 00512 Fl_Window_Type Fl_Window_type; 00513 00514 // Resize from window manager... 00515 void Overlay_Window::resize(int X,int Y,int W,int H) { 00516 Fl_Widget* t = resizable(); resizable(0); 00517 00518 // do not set the mod flag if the window was not resized. In FLUID, all 00519 // windows are opened without a given x/y position, so modifying x/y 00520 // should not mark the project as dirty 00521 if (W!=w() || H!=h()) 00522 set_modflag(1); 00523 00524 Fl_Overlay_Window::resize(X,Y,W,H); 00525 resizable(t); 00526 update_xywh(); 00527 } 00528 00529 // calculate actual move by moving mouse position (mx,my) to 00530 // nearest multiple of gridsize, and snap to original position 00531 void Fl_Window_Type::newdx() { 00532 int mydx, mydy; 00533 if (Fl::event_state(FL_ALT) || !snap) { 00534 mydx = mx-x1; 00535 mydy = my-y1; 00536 00537 if (abs(mydx) < 2 && abs(mydy) < 2) mydx = mydy = 0; 00538 } else { 00539 int dx0 = mx-x1; 00540 int ix = (drag&RIGHT) ? br : bx; 00541 mydx = gridx ? ((ix+dx0+gridx/2)/gridx)*gridx - ix : dx0; 00542 if (dx0 > snap) { 00543 if (mydx < 0) mydx = 0; 00544 } else if (dx0 < -snap) { 00545 if (mydx > 0) mydx = 0; 00546 } else 00547 mydx = 0; 00548 int dy0 = my-y1; 00549 int iy = (drag&BOTTOM) ? by : bt; 00550 mydy = gridy ? ((iy+dy0+gridy/2)/gridy)*gridy - iy : dy0; 00551 if (dy0 > snap) { 00552 if (mydy < 0) mydy = 0; 00553 } else if (dy0 < -snap) { 00554 if (mydy > 0) mydy = 0; 00555 } else 00556 mydy = 0; 00557 } 00558 00559 if (!(drag & (DRAG | BOX | LEFT | RIGHT))) { 00560 mydx = 0; 00561 dx = 0; 00562 } 00563 00564 if (!(drag & (DRAG | BOX | TOP | BOTTOM))) { 00565 mydy = 0; 00566 dy = 0; 00567 } 00568 00569 if (dx != mydx || dy != mydy) { 00570 dx = mydx; dy = mydy; 00571 ((Overlay_Window *)o)->redraw_overlay(); 00572 } 00573 } 00574 00575 // Move a widget according to dx and dy calculated above 00576 void Fl_Window_Type::newposition(Fl_Widget_Type *myo,int &X,int &Y,int &R,int &T) { 00577 X = myo->o->x(); 00578 Y = myo->o->y(); 00579 R = X+myo->o->w(); 00580 T = Y+myo->o->h(); 00581 if (!drag) return; 00582 if (drag&DRAG) { 00583 X += dx; 00584 Y += dy; 00585 R += dx; 00586 T += dy; 00587 } else { 00588 if (drag&LEFT) { 00589 if (X==bx) { 00590 X += dx; 00591 } else { 00592 if (X<bx+dx) X = bx+dx; 00593 } 00594 } 00595 if (drag&TOP) { 00596 if (Y==by) { 00597 Y += dy; 00598 } else { 00599 if (Y<by+dy) Y = by+dy; 00600 } 00601 } 00602 if (drag&RIGHT) { 00603 if (R==br) { 00604 R += dx; 00605 } else { 00606 if (R>br+dx) R = br+dx; 00607 } 00608 } 00609 if (drag&BOTTOM) { 00610 if (T==bt) { 00611 T += dy; 00612 } else { 00613 if (T>bt+dx) T = bt+dx; 00614 } 00615 } 00616 } 00617 if (R<X) {int n = X; X = R; R = n;} 00618 if (T<Y) {int n = Y; Y = T; T = n;} 00619 } 00620 00621 // draw a vertical arrow pointing toward y2 00622 static void draw_v_arrow(int x, int y1, int y2) { 00623 int dy = (y1>y2) ? -1 : 1 ; 00624 fl_yxline(x, y1, y2); 00625 fl_xyline(x-4, y2, x+4); 00626 fl_line(x-2, y2-dy*5, x, y2-dy); 00627 fl_line(x+2, y2-dy*5, x, y2-dy); 00628 } 00629 00630 static void draw_h_arrow(int x1, int y, int x2) { 00631 int dx = (x1>x2) ? -1 : 1 ; 00632 fl_xyline(x1, y, x2); 00633 fl_yxline(x2, y-4, y+4); 00634 fl_line(x2-dx*5, y-2, x2-dx, y); 00635 fl_line(x2-dx*5, y+2, x2-dx, y); 00636 } 00637 00638 static void draw_top_brace(const Fl_Widget *w) { 00639 fl_yxline(w->x(), w->y()-2, w->y()+6); 00640 fl_yxline(w->x()+w->w()-1, w->y()-2, w->y()+6); 00641 fl_xyline(w->x()-2, w->y(), w->x()+w->w()+1); 00642 } 00643 00644 static void draw_left_brace(const Fl_Widget *w) { 00645 fl_xyline(w->x()-2, w->y(), w->x()+6); 00646 fl_xyline(w->x()-2, w->y()+w->h()-1, w->x()+6); 00647 fl_yxline(w->x(), w->y()-2, w->y()+w->h()+1); 00648 } 00649 00650 static void draw_right_brace(const Fl_Widget *w) { 00651 int xx = w->x() + w->w() - 1; 00652 fl_xyline(xx-6, w->y(), xx+2); 00653 fl_xyline(xx-6, w->y()+w->h()-1, xx+2); 00654 fl_yxline(xx, w->y()-2, w->y()+w->h()+1); 00655 } 00656 00657 static void draw_bottom_brace(const Fl_Widget *w) { 00658 int yy = w->y() + w->h() - 1; 00659 fl_yxline(w->x(), yy-6, yy+2); 00660 fl_yxline(w->x()+w->w()-1, yy-6, yy+2); 00661 fl_xyline(w->x()-2, yy, w->x()+w->w()+1); 00662 } 00663 00664 static void draw_height(int x, int y, int b, Fl_Align a) { 00665 char buf[16]; 00666 int h = b - y; 00667 sprintf(buf, "%d", h); 00668 fl_font(FL_HELVETICA, 9); 00669 int lw = (int)fl_width(buf); 00670 int lx; 00671 00672 b --; 00673 if (h < 30) { 00674 // Move height to the side... 00675 if (a == FL_ALIGN_LEFT) lx = x - lw - 2; 00676 else lx = x + 2; 00677 00678 fl_yxline(x, y, b); 00679 } else { 00680 // Put height inside the arrows... 00681 lx = x - lw / 2; 00682 00683 fl_yxline(x, y, y + (h - 11) / 2); 00684 fl_yxline(x, y + (h + 11) / 2, b); 00685 } 00686 00687 // Draw the height... 00688 fl_draw(buf, lx, y + (h + 9) / 2); 00689 00690 // Draw the arrowheads... 00691 fl_line(x-2, y+5, x, y+1, x+2, y+5); 00692 fl_line(x-2, b-5, x, b-1, x+2, b-5); 00693 00694 // Draw the end lines... 00695 fl_xyline(x - 4, y, x + 4); 00696 fl_xyline(x - 4, b, x + 4); 00697 } 00698 00699 static void draw_width(int x, int y, int r, Fl_Align a) { 00700 char buf[16]; 00701 int w = r-x; 00702 sprintf(buf, "%d", w); 00703 fl_font(FL_HELVETICA, 9); 00704 int lw = (int)fl_width(buf); 00705 int ly = y + 4; 00706 00707 r --; 00708 00709 if (lw > (w - 20)) { 00710 // Move width above/below the arrows... 00711 if (a == FL_ALIGN_TOP) ly -= 10; 00712 else ly += 10; 00713 00714 fl_xyline(x, y, r); 00715 } else { 00716 // Put width inside the arrows... 00717 fl_xyline(x, y, x + (w - lw - 2) / 2); 00718 fl_xyline(x + (w + lw + 2) / 2, y, r); 00719 } 00720 00721 // Draw the width... 00722 fl_draw(buf, x + (w - lw) / 2, ly); 00723 00724 // Draw the arrowheads... 00725 fl_line(x+5, y-2, x+1, y, x+5, y+2); 00726 fl_line(r-5, y-2, r-1, y, r-5, y+2); 00727 00728 // Draw the end lines... 00729 fl_yxline(x, y - 4, y + 4); 00730 fl_yxline(r, y - 4, y + 4); 00731 } 00732 00733 void Fl_Window_Type::draw_overlay() { 00734 if (recalc) { 00735 bx = o->w(); by = o->h(); br = 0; bt = 0; 00736 numselected = 0; 00737 for (Fl_Type *q=next; q && q->level>level; q=q->next) 00738 if (q->selected && q->is_widget() && !q->is_menu_item()) { 00739 numselected++; 00740 Fl_Widget_Type* myo = (Fl_Widget_Type*)q; 00741 if (myo->o->x() < bx) bx = myo->o->x(); 00742 if (myo->o->y() < by) by = myo->o->y(); 00743 if (myo->o->x()+myo->o->w() > br) br = myo->o->x()+myo->o->w(); 00744 if (myo->o->y()+myo->o->h() > bt) bt = myo->o->y()+myo->o->h(); 00745 } 00746 recalc = 0; 00747 sx = bx; sy = by; sr = br; st = bt; 00748 } 00749 fl_color(FL_RED); 00750 if (drag==BOX && (x1 != mx || y1 != my)) { 00751 int x = x1; int r = mx; if (x > r) {x = mx; r = x1;} 00752 int y = y1; int b = my; if (y > b) {y = my; b = y1;} 00753 fl_rect(x,y,r-x,b-y); 00754 } 00755 if (overlays_invisible && !drag) return; 00756 if (selected) fl_rect(0,0,o->w(),o->h()); 00757 if (!numselected) return; 00758 int mybx,myby,mybr,mybt; 00759 int mysx,mysy,mysr,myst; 00760 mybx = mysx = o->w(); myby = mysy = o->h(); mybr = mysr = 0; mybt = myst = 0; 00761 Fl_Type *selection = 0L; // used to store the one selected widget (if n==1) 00762 for (Fl_Type *q=next; q && q->level>level; q = q->next) 00763 if (q->selected && q->is_widget() && !q->is_menu_item()) { 00764 selection = q; 00765 Fl_Widget_Type* myo = (Fl_Widget_Type*)q; 00766 int x,y,r,t; 00767 newposition(myo,x,y,r,t); 00768 if (!show_guides || !drag || numselected != 1) fl_rect(x,y,r-x,t-y); 00769 if (x < mysx) mysx = x; 00770 if (y < mysy) mysy = y; 00771 if (r > mysr) mysr = r; 00772 if (t > myst) myst = t; 00773 if (!(myo->o->align() & FL_ALIGN_INSIDE)) { 00774 // Adjust left/right/top/bottom for top/bottom labels... 00775 int ww, hh; 00776 ww = (myo->o->align() & FL_ALIGN_WRAP) ? myo->o->w() : 0; 00777 hh = myo->o->labelsize(); 00778 myo->o->measure_label(ww, hh); 00779 if (myo->o->align() & FL_ALIGN_TOP) y -= hh; 00780 else if (myo->o->align() & FL_ALIGN_BOTTOM) t += hh; 00781 else if (myo->o->align() & FL_ALIGN_LEFT) x -= ww + 4; 00782 else if (myo->o->align() & FL_ALIGN_RIGHT) r += ww + 4; 00783 } 00784 if (x < mybx) mybx = x; 00785 if (y < myby) myby = y; 00786 if (r > mybr) mybr = r; 00787 if (t > mybt) mybt = t; 00788 } 00789 if (selected) return; 00790 00791 if (show_guides && drag) { 00792 // draw overlays for UI Guideline distances 00793 // - check for distance to the window edge 00794 // * FLTK suggests 10 pixels from the edge 00795 int d; 00796 int xsp, ysp; 00797 int mybx_bak = mybx, myby_bak = myby, mybr_bak = mybr, mybt_bak = mybt; 00798 Fl_Widget_Type *mysel = (Fl_Widget_Type *)selection; 00799 00800 00801 ideal_spacing(xsp, ysp); 00802 00803 if (drag) { 00804 // Check top spacing... 00805 if (abs(d = myby - ysp) < 3) { 00806 dy -= d; 00807 if (drag & DRAG) mybt -= d; 00808 myby -= d; 00809 draw_v_arrow(mybx+5, myby, 0); 00810 } 00811 00812 // Check bottom spacing... 00813 if (abs(d = o->h() - mybt - ysp) < 3) { 00814 dy += d; 00815 if (drag & DRAG) myby += d; 00816 mybt += d; 00817 draw_v_arrow(mybx+5, mybt, o->h()); 00818 } 00819 00820 // Check left spacing... 00821 if (abs(d = mybx - xsp) < 3) { 00822 dx -= d; 00823 if (drag & DRAG) mybr -= d; 00824 mybx -= d; 00825 draw_h_arrow(mybx, myby+5, 0); 00826 } 00827 00828 // Check right spacing... 00829 if (abs(d = o->w() - mybr - xsp) < 3) { 00830 dx += d; 00831 if (drag & DRAG) mybx += d; 00832 mybr += d; 00833 draw_h_arrow(mybr, myby+5, o->w()); 00834 } 00835 } 00836 00837 if (numselected==1 && selection && !(drag & DRAG)) { 00838 // Check ideal sizes 00839 int x,y,r,t; 00840 newposition(mysel,x,y,r,t); 00841 int w = r-x; 00842 int h = t-y; 00843 int iw = w, ih = h; 00844 00845 mysel->ideal_size(iw, ih); 00846 00847 if (drag & (TOP | BOTTOM)) { 00848 // Check height 00849 if (abs(d = ih - h) < 5) { 00850 // Resize height 00851 if (drag & TOP) { 00852 myby -= d; 00853 y -= d; 00854 dy -= d; 00855 } else { 00856 mybt += d; 00857 t += d; 00858 dy += d; 00859 } 00860 } 00861 00862 // Draw height guide 00863 draw_height(x < 50 ? x+10 : x-10, y, t, 00864 x < 50 ? FL_ALIGN_RIGHT : FL_ALIGN_LEFT); 00865 } 00866 00867 if (drag & (LEFT | RIGHT)) { 00868 // Check width 00869 if (abs(d = iw - w) < 5) { 00870 // Resize width 00871 if (drag & LEFT) { 00872 mybx -= d; 00873 x -= d; 00874 dx -= d; 00875 } else { 00876 mybr += d; 00877 r += d; 00878 dx += d; 00879 } 00880 } 00881 00882 // Draw width guide 00883 draw_width(x, y < 50 ? y+10 : y-10, r, 00884 y < 50 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP); 00885 } 00886 } 00887 00888 // Check spacing and alignment between individual widgets 00889 if (drag && selection->is_widget()) { 00890 for (Fl_Type *q=next; q && q->level>level; q = q->next) 00891 if (q != selection && q->is_widget()) { 00892 Fl_Widget_Type *qw = (Fl_Widget_Type*)q; 00893 // Only check visible widgets... 00894 if (!qw->o->visible_r()) continue; 00895 00896 // Get bounding box of widget... 00897 int qx = qw->o->x(); 00898 int qr = qw->o->x() + qw->o->w(); 00899 int qy = qw->o->y(); 00900 int qt = qw->o->y() + qw->o->h(); 00901 00902 if (!(qw->o->align() & FL_ALIGN_INSIDE)) { 00903 // Adjust top/bottom for top/bottom labels... 00904 int ww, hh; 00905 ww = qw->o->w(); 00906 hh = qw->o->labelsize(); 00907 qw->o->measure_label(ww, hh); 00908 if (qw->o->align() & FL_ALIGN_TOP) qy -= hh; 00909 if (qw->o->align() & FL_ALIGN_BOTTOM) qt += hh; 00910 } 00911 00912 // Do horizontal alignment when the widget is within 25 00913 // pixels vertically... 00914 if (fl_min(abs(qy - mysel->o->y() - mysel->o->h()), 00915 abs(mysel->o->y() - qt)) < 25) { 00916 // Align to left of other widget... 00917 if ((drag & (LEFT | DRAG)) && abs(d = mybx - qx) < 3) { 00918 dx += d; 00919 mybx += d; 00920 if (drag & DRAG) mybr += d; 00921 00922 draw_left_brace(qw->o); 00923 } 00924 00925 // Align to right of other widget... 00926 if ((drag & (RIGHT | DRAG)) && 00927 abs(d = qr - mybr) < 3) { 00928 dx += d; 00929 if (drag & DRAG) mybx += d; 00930 mybr += d; 00931 00932 draw_right_brace(qw->o); 00933 } 00934 } 00935 00936 // Align to top of other widget... 00937 if ((drag & (TOP | DRAG)) && abs(d = myby - qy) < 3) { 00938 dy += d; 00939 myby += d; 00940 if (drag & DRAG) mybt += d; 00941 00942 draw_top_brace(qw->o); 00943 } 00944 00945 // Align to bottom of other widget... 00946 if ((drag & (BOTTOM | DRAG)) && abs(d = qt - mybt) < 3) { 00947 dy += d; 00948 if (drag & DRAG) myby += d; 00949 mybt += d; 00950 00951 draw_bottom_brace(qw->o); 00952 } 00953 00954 // Check spacing between widgets 00955 if (mysel->is_group()) mysel->ideal_spacing(xsp, ysp); 00956 else qw->ideal_spacing(xsp, ysp); 00957 00958 if ((qt)>=myby && qy<=mybt) { 00959 if (drag & (LEFT | DRAG)) { 00960 // Compare left of selected to left of current 00961 if (abs(d = qx - mybx - xsp) >= 3) 00962 d = qx - mybx + xsp; 00963 00964 if (abs(d) < 3) { 00965 dx += d; 00966 mybx += d; 00967 if (drag & DRAG) mybr += d; 00968 00969 // Draw left arrow 00970 draw_h_arrow(mybx, (myby+mybt)/2, qx); 00971 } 00972 00973 // Compare left of selected to right of current 00974 if (abs(d = qr - mybx - xsp) >= 3) 00975 d = qr - mybx + xsp; 00976 00977 if (abs(d) < 3) { 00978 dx += d; 00979 mybx += d; 00980 if (drag & DRAG) mybr += d; 00981 00982 // Draw left arrow 00983 draw_h_arrow(mybx, (myby+mybt)/2, qr); 00984 } 00985 } 00986 00987 if (drag & (RIGHT | DRAG)) { 00988 // Compare right of selected to left of current 00989 if (abs(d = qx - mybr - xsp) >= 3) 00990 d = qx - mybr + xsp; 00991 00992 if (abs(d) < 3) { 00993 dx += d; 00994 if (drag & DRAG) mybx += d; 00995 mybr += d; 00996 00997 // Draw right arrow 00998 draw_h_arrow(mybr, (myby+mybt)/2, qx); 00999 } 01000 01001 // Compare right of selected to right of current 01002 if (abs(d = qr - mybr + xsp) >= 3) 01003 d = qr - mybr - xsp; 01004 01005 if (abs(d) < 3) { 01006 dx += d; 01007 if (drag & DRAG) mybx += d; 01008 mybr += d; 01009 01010 // Draw right arrow 01011 draw_h_arrow(mybr, (myby+mybt)/2, qr); 01012 } 01013 } 01014 } 01015 01016 if (qr>=mybx && qx<=mybr) { 01017 // Compare top of selected to top of current 01018 if (drag & (TOP | DRAG)) { 01019 if (abs(d = qy - myby - ysp) >= 3) 01020 d = qy - myby + ysp; 01021 01022 if (abs(d) < 3) { 01023 dy += d; 01024 myby += d; 01025 if (drag & DRAG) mybt += d; 01026 01027 // Draw up arrow... 01028 draw_v_arrow((mybx+mybr)/2, myby, qy); 01029 } 01030 01031 // Compare top of selected to bottom of current 01032 if (abs(d = qt - myby - ysp) >= 3) 01033 d = qt - myby + ysp; 01034 01035 if (abs(d) < 3) { 01036 dy += d; 01037 myby += d; 01038 if (drag & DRAG) mybt += d; 01039 01040 // Draw up arrow... 01041 draw_v_arrow((mybx+mybr)/2, myby, qt); 01042 } 01043 } 01044 01045 // Compare bottom of selected to top of current 01046 if (drag & (BOTTOM | DRAG)) { 01047 if (abs(d = qy - mybt - ysp) >= 3) 01048 d = qy - mybt + ysp; 01049 01050 if (abs(d) < 3) { 01051 dy += d; 01052 if (drag & DRAG) myby += d; 01053 mybt += d; 01054 01055 // Draw down arrow... 01056 draw_v_arrow((mybx+mybr)/2, mybt, qy); 01057 } 01058 01059 // Compare bottom of selected to bottom of current 01060 if (abs(d = qt - mybt - ysp) >= 3) 01061 d = qt - mybt + ysp; 01062 01063 if (abs(d) < 3) { 01064 dy += d; 01065 if (drag & DRAG) myby += d; 01066 mybt += d; 01067 01068 // Draw down arrow... 01069 draw_v_arrow((mybx+mybr)/2, mybt, qt); 01070 } 01071 } 01072 } 01073 } 01074 } 01075 mysx += mybx-mybx_bak; mysr += mybr-mybr_bak; 01076 mysy += myby-myby_bak; myst += mybt-mybt_bak; 01077 } 01078 // align the snapping selection box with the box we draw. 01079 sx = mysx; sy = mysy; sr = mysr; st = myst; 01080 01081 // Draw selection box + resize handles... 01082 // draw box including all labels 01083 fl_line_style(FL_DOT); 01084 fl_rect(mybx,myby,mybr-mybx,mybt-myby); 01085 fl_line_style(FL_SOLID); 01086 // draw box excluding labels 01087 fl_rect(mysx,mysy,mysr-mysx,myst-mysy); 01088 fl_rectf(mysx,mysy,5,5); 01089 fl_rectf(mysr-5,mysy,5,5); 01090 fl_rectf(mysr-5,myst-5,5,5); 01091 fl_rectf(mysx,myst-5,5,5); 01092 } 01093 01094 extern Fl_Menu_Item Main_Menu[]; 01095 01096 // Calculate new bounding box of selected widgets: 01097 void Fl_Window_Type::fix_overlay() { 01098 Main_Menu[40].label("Hide O&verlays"); 01099 overlays_invisible = 0; 01100 recalc = 1; 01101 ((Overlay_Window *)(this->o))->redraw_overlay(); 01102 } 01103 01104 // check if we must redraw any parent of tabs/wizard type 01105 void check_redraw_corresponding_parent(Fl_Type *s) { 01106 Fl_Widget_Type * prev_parent = 0; 01107 if( !s || !s->selected || !s->is_widget()) return; 01108 for (Fl_Type *i=s; i && i->parent; i=i->parent) { 01109 if (i->is_group() && prev_parent && 01110 (!strcmp(i->type_name(), "Fl_Tabs") || 01111 !strcmp(i->type_name(), "Fl_Wizard"))) { 01112 ((Fl_Tabs*)((Fl_Widget_Type*)i)->o)->value(prev_parent->o); 01113 return; 01114 } 01115 if (i->is_group() && s->is_widget()) 01116 prev_parent = (Fl_Widget_Type*)i; 01117 } 01118 } 01119 01120 // do that for every window (when selected set changes): 01121 void redraw_overlays() { 01122 for (Fl_Type *o=Fl_Type::first; o; o=o->next) 01123 if (o->is_window()) ((Fl_Window_Type*)o)->fix_overlay(); 01124 } 01125 01126 void toggle_overlays(Fl_Widget *,void *) { 01127 overlays_invisible = !overlays_invisible; 01128 01129 if (overlays_invisible) Main_Menu[40].label("Show O&verlays"); 01130 else Main_Menu[40].label("Hide O&verlays"); 01131 01132 for (Fl_Type *o=Fl_Type::first; o; o=o->next) 01133 if (o->is_window()) { 01134 Fl_Widget_Type* w = (Fl_Widget_Type*)o; 01135 ((Overlay_Window*)(w->o))->redraw_overlay(); 01136 } 01137 } 01138 01139 extern void select(Fl_Type *,int); 01140 extern void select_only(Fl_Type *); 01141 extern void deselect(); 01142 extern Fl_Type* in_this_only; 01143 extern void fix_group_size(Fl_Type *t); 01144 01145 extern Fl_Menu_Item Main_Menu[]; 01146 extern Fl_Menu_Item New_Menu[]; 01147 01148 // move the selected children according to current dx,dy,drag state: 01149 void Fl_Window_Type::moveallchildren() 01150 { 01151 undo_checkpoint(); 01152 Fl_Type *i; 01153 for (i=next; i && i->level>level;) { 01154 if (i->selected && i->is_widget() && !i->is_menu_item()) { 01155 Fl_Widget_Type* myo = (Fl_Widget_Type*)i; 01156 int x,y,r,t; 01157 newposition(myo,x,y,r,t); 01158 myo->o->resize(x,y,r-x,t-y); 01159 // move all the children, whether selected or not: 01160 Fl_Type* p; 01161 for (p = myo->next; p && p->level>myo->level; p = p->next) 01162 if (p->is_widget() && !p->is_menu_item()) { 01163 Fl_Widget_Type* myo2 = (Fl_Widget_Type*)p; 01164 int X,Y,R,T; 01165 newposition(myo2,X,Y,R,T); 01166 myo2->o->resize(X,Y,R-X,T-Y); 01167 } 01168 i = p; 01169 } else { 01170 i = i->next; 01171 } 01172 } 01173 for (i=next; i && i->level>level; i=i->next) 01174 fix_group_size(i); 01175 o->redraw(); 01176 recalc = 1; 01177 ((Overlay_Window *)(this->o))->redraw_overlay(); 01178 set_modflag(1); 01179 dx = dy = 0; 01180 01181 update_xywh(); 01182 } 01183 01184 int Fl_Window_Type::handle(int event) { 01185 static Fl_Type* selection; 01186 switch (event) { 01187 case FL_PUSH: 01188 x1 = mx = Fl::event_x(); 01189 y1 = my = Fl::event_y(); 01190 drag = dx = dy = 0; 01191 // test for popup menu: 01192 if (Fl::event_button() >= 3) { 01193 in_this_only = this; // modifies how some menu items work. 01194 static const Fl_Menu_Item* myprev; 01195 const Fl_Menu_Item* m = New_Menu->popup(mx,my,"New",myprev); 01196 if (m && m->callback()) {myprev = m; m->do_callback(this->o);} 01197 in_this_only = 0; 01198 return 1; 01199 } 01200 // find the innermost item clicked on: 01201 selection = this; 01202 {for (Fl_Type* i=next; i && i->level>level; i=i->next) 01203 if (i->is_widget() && !i->is_menu_item()) { 01204 Fl_Widget_Type* myo = (Fl_Widget_Type*)i; 01205 for (Fl_Widget *o1 = myo->o; o1; o1 = o1->parent()) 01206 if (!o1->visible()) goto CONTINUE2; 01207 if (Fl::event_inside(myo->o)) { 01208 selection = myo; 01209 if (Fl::event_clicks()==1) 01210 reveal_in_browser(myo); 01211 } 01212 CONTINUE2:; 01213 }} 01214 // see if user grabs edges of selected region: 01215 if (numselected && !(Fl::event_state(FL_SHIFT)) && 01216 mx<=br+snap && mx>=bx-snap && my<=bt+snap && my>=by-snap) { 01217 int snap1 = snap>5 ? snap : 5; 01218 int w1 = (br-bx)/4; if (w1 > snap1) w1 = snap1; 01219 if (mx>=br-w1) drag |= RIGHT; 01220 else if (mx<bx+w1) drag |= LEFT; 01221 w1 = (bt-by)/4; if (w1 > snap1) w1 = snap1; 01222 if (my<=by+w1) drag |= TOP; 01223 else if (my>bt-w1) drag |= BOTTOM; 01224 if (!drag) drag = DRAG; 01225 } 01226 // do object-specific selection of other objects: 01227 {Fl_Type* t = selection->click_test(mx, my); 01228 if (t) { 01229 //if (t == selection) return 1; // indicates mouse eaten w/o change 01230 if (Fl::event_state(FL_SHIFT)) { 01231 Fl::event_is_click(0); 01232 select(t, !t->selected); 01233 } else { 01234 deselect(); 01235 select(t, 1); 01236 if (t->is_menu_item()) t->open(); 01237 } 01238 selection = t; 01239 drag = 0; 01240 } else { 01241 if (!drag) drag = BOX; // if all else fails, start a new selection region 01242 }} 01243 return 1; 01244 01245 case FL_DRAG: 01246 if (!drag) return 0; 01247 mx = Fl::event_x(); 01248 my = Fl::event_y(); 01249 newdx(); 01250 return 1; 01251 01252 case FL_RELEASE: 01253 if (!drag) return 0; 01254 mx = Fl::event_x(); 01255 my = Fl::event_y(); 01256 if (drag != BOX && (dx || dy || !Fl::event_is_click())) { 01257 if (dx || dy) moveallchildren(); 01258 } else if ((Fl::event_clicks() || Fl::event_state(FL_CTRL))) { 01259 Fl_Widget_Type::open(); 01260 } else { 01261 if (mx<x1) {int t = x1; x1 = mx; mx = t;} 01262 if (my<y1) {int t = y1; y1 = my; my = t;} 01263 int n = 0; 01264 int toggle = Fl::event_state(FL_SHIFT); 01265 // clear selection on everything: 01266 if (!toggle) deselect(); else Fl::event_is_click(0); 01267 // select everything in box: 01268 for (Fl_Type*i=next; i&&i->level>level; i=i->next) 01269 if (i->is_widget() && !i->is_menu_item()) { 01270 Fl_Widget_Type* myo = (Fl_Widget_Type*)i; 01271 for (Fl_Widget *o1 = myo->o; o1; o1 = o1->parent()) 01272 if (!o1->visible()) goto CONTINUE; 01273 if (Fl::event_inside(myo->o)) selection = myo; 01274 if (myo->o->x()>=x1 && myo->o->y()>y1 && 01275 myo->o->x()+myo->o->w()<mx && myo->o->y()+myo->o->h()<my) { 01276 n++; 01277 select(myo, toggle ? !myo->selected : 1); 01278 } 01279 CONTINUE:; 01280 } 01281 // if nothing in box, select what was clicked on: 01282 if (!n) { 01283 select(selection, toggle ? !selection->selected : 1); 01284 } 01285 } 01286 drag = 0; 01287 ((Overlay_Window *)o)->redraw_overlay(); 01288 return 1; 01289 01290 case FL_KEYBOARD: { 01291 01292 int backtab = 0; 01293 switch (Fl::event_key()) { 01294 01295 case FL_Escape: 01296 ((Fl_Window*)o)->hide(); 01297 return 1; 01298 01299 case FL_Tab: { 01300 if (Fl::event_state(FL_SHIFT)) backtab = 1; 01301 // find current child: 01302 Fl_Type *i = Fl_Type::current; 01303 while (i && (!i->is_widget() || i->is_menu_item())) i = i->parent; 01304 if (!i) return 0; 01305 Fl_Type *p = i->parent; 01306 while (p && p != this) p = p->parent; 01307 if (!p || !p->is_widget()) { 01308 i = next; if (!i || i->level <= level) return 0; 01309 } 01310 p = i; 01311 for (;;) { 01312 i = backtab ? i->prev : i->next; 01313 if (!i || i->level <= level) {i = p; break;} 01314 if (i->is_widget() && !i->is_menu_item()) break; 01315 } 01316 deselect(); select(i,1); 01317 return 1;} 01318 01319 case FL_Left: dx = -1; dy = 0; goto ARROW; 01320 case FL_Right: dx = +1; dy = 0; goto ARROW; 01321 case FL_Up: dx = 0; dy = -1; goto ARROW; 01322 case FL_Down: dx = 0; dy = +1; goto ARROW; 01323 ARROW: 01324 // for some reason BOTTOM/TOP are swapped... should be fixed... 01325 drag = (Fl::event_state(FL_SHIFT)) ? (RIGHT|TOP) : DRAG; 01326 if (Fl::event_state(FL_CTRL)) {dx *= gridx; dy *= gridy;} 01327 moveallchildren(); 01328 drag = 0; 01329 return 1; 01330 01331 case 'o': 01332 toggle_overlays(0, 0); 01333 break; 01334 01335 default: 01336 return 0; 01337 }} 01338 01339 case FL_SHORTCUT: { 01340 in_this_only = this; // modifies how some menu items work. 01341 const Fl_Menu_Item* m = Main_Menu->test_shortcut(); 01342 if (m && m->callback()) m->do_callback(this->o); 01343 in_this_only = 0; 01344 return (m != 0);} 01345 01346 default: 01347 return 0; 01348 } 01349 } 01350 01352 01353 #include <stdio.h> 01354 #include "../src/flstring.h" 01355 01356 void Fl_Window_Type::write_code1() { 01357 Fl_Widget_Type::write_code1(); 01358 } 01359 01360 void Fl_Window_Type::write_code2() { 01361 const char *var = is_class() ? "this" : name() ? name() : "o"; 01362 write_extra_code(); 01363 if (modal) write_c("%s%s->set_modal();\n", indent(), var); 01364 else if (non_modal) write_c("%s%s->set_non_modal();\n", indent(), var); 01365 if (!((Fl_Window*)o)->border()) { 01366 write_c("%s%s->clear_border();\n", indent(), var); 01367 } 01368 if (xclass) { 01369 write_c("%s%s->xclass(", indent(), var); 01370 write_cstring(xclass); 01371 write_c(");\n"); 01372 } 01373 if (sr_max_w || sr_max_h) { 01374 write_c("%s%s->size_range(%d, %d, %d, %d);\n", indent(), var, 01375 sr_min_w, sr_min_h, sr_max_w, sr_max_h); 01376 } else if (sr_min_w || sr_min_h) { 01377 write_c("%s%s->size_range(%d, %d);\n", indent(), var, sr_min_w, sr_min_h); 01378 } 01379 write_c("%s%s->end();\n", indent(), var); 01380 if (((Fl_Window*)o)->resizable() == o) 01381 write_c("%s%s->resizable(%s);\n", indent(), var, var); 01382 write_block_close(); 01383 } 01384 01385 void Fl_Window_Type::write_properties() { 01386 Fl_Widget_Type::write_properties(); 01387 if (modal) write_string("modal"); 01388 else if (non_modal) write_string("non_modal"); 01389 if (!((Fl_Window*)o)->border()) write_string("noborder"); 01390 if (xclass) {write_string("xclass"); write_word(xclass);} 01391 if (sr_min_w || sr_min_h || sr_max_w || sr_max_h) 01392 write_string("size_range {%d %d %d %d}", sr_min_w, sr_min_h, sr_max_w, sr_max_h); 01393 if (o->visible()) write_string("visible"); 01394 } 01395 01396 extern int pasteoffset; 01397 void Fl_Window_Type::read_property(const char *c) { 01398 if (!strcmp(c,"modal")) { 01399 modal = 1; 01400 } else if (!strcmp(c,"non_modal")) { 01401 non_modal = 1; 01402 } else if (!strcmp(c, "visible")) { 01403 if (Fl::first_window()) open(); // only if we are using user interface 01404 } else if (!strcmp(c,"noborder")) { 01405 ((Fl_Window*)o)->border(0); 01406 } else if (!strcmp(c,"xclass")) { 01407 storestring(read_word(),xclass); 01408 ((Fl_Window*)o)->xclass(xclass); 01409 } else if (!strcmp(c,"size_range")) { 01410 int mw, mh, MW, MH; 01411 if (sscanf(read_word(),"%d %d %d %d",&mw,&mh,&MW,&MH) == 4) { 01412 sr_min_w = mw; sr_min_h = mh; sr_max_w = MW; sr_max_h = MH; 01413 } 01414 } else if (!strcmp(c,"xywh")) { 01415 Fl_Widget_Type::read_property(c); 01416 pasteoffset = 0; // make it not apply to contents 01417 } else { 01418 Fl_Widget_Type::read_property(c); 01419 } 01420 } 01421 01422 int Fl_Window_Type::read_fdesign(const char* propname, const char* value) { 01423 int x; 01424 o->box(FL_NO_BOX); // because fdesign always puts an Fl_Box next 01425 if (!strcmp(propname,"Width")) { 01426 if (sscanf(value,"%d",&x) == 1) o->size(x,o->h()); 01427 } else if (!strcmp(propname,"Height")) { 01428 if (sscanf(value,"%d",&x) == 1) o->size(o->w(),x); 01429 } else if (!strcmp(propname,"NumberofWidgets")) { 01430 return 1; // we can figure out count from file 01431 } else if (!strcmp(propname,"border")) { 01432 if (sscanf(value,"%d",&x) == 1) ((Fl_Window*)o)->border(x); 01433 } else if (!strcmp(propname,"title")) { 01434 label(value); 01435 } else { 01436 return Fl_Widget_Type::read_fdesign(propname,value); 01437 } 01438 return 1; 01439 } 01440 01442 01443 Fl_Widget_Class_Type Fl_Widget_Class_type; 01444 Fl_Widget_Class_Type *current_widget_class = 0; 01445 01446 Fl_Type *Fl_Widget_Class_Type::make() { 01447 Fl_Type *p = Fl_Type::current; 01448 while (p && (!p->is_decl_block() || (p->is_widget() && p->is_class()))) p = p->parent; 01449 Fl_Widget_Class_Type *myo = new Fl_Widget_Class_Type(); 01450 myo->name("UserInterface"); 01451 01452 if (!this->o) {// template widget 01453 this->o = new Fl_Window(100,100); 01454 Fl_Group::current(0); 01455 } 01456 // Set the size ranges for this window; in order to avoid opening the 01457 // X display we use an arbitrary maximum size... 01458 ((Fl_Window *)(this->o))->size_range(gridx, gridy, 01459 3072, 2048, 01460 gridx, gridy, 0); 01461 myo->factory = this; 01462 myo->drag = 0; 01463 myo->numselected = 0; 01464 Overlay_Window *w = new Overlay_Window(100,100); 01465 w->window = myo; 01466 myo->o = w; 01467 myo->add(p); 01468 myo->modal = 0; 01469 myo->non_modal = 0; 01470 myo->wc_relative = 0; 01471 01472 return myo; 01473 } 01474 01475 void Fl_Widget_Class_Type::write_properties() { 01476 Fl_Window_Type::write_properties(); 01477 if (wc_relative) write_string("position_relative"); 01478 } 01479 01480 void Fl_Widget_Class_Type::read_property(const char *c) { 01481 if (!strcmp(c,"position_relative")) { 01482 wc_relative = 1; 01483 } else { 01484 Fl_Window_Type::read_property(c); 01485 } 01486 } 01487 01488 void Fl_Widget_Class_Type::write_code1() { 01489 #if 0 01490 Fl_Widget_Type::write_code1(); 01491 #endif // 0 01492 01493 current_widget_class = this; 01494 write_public_state = 1; 01495 01496 const char *c = subclass(); 01497 if (!c) c = "Fl_Group"; 01498 01499 write_h("\nclass %s : public %s {\n", name(), c); 01500 if (strstr(c, "Window")) { 01501 write_h(" void _%s();\n", name()); 01502 write_h("public:\n"); 01503 write_h(" %s(int X, int Y, int W, int H, const char *L = 0);\n", name()); 01504 write_h(" %s(int W, int H, const char *L = 0);\n", name()); 01505 write_h(" %s();\n", name()); 01506 01507 // a constructor with all four dimensions plus label 01508 write_c("%s::%s(int X, int Y, int W, int H, const char *L)\n", name(), name()); 01509 write_c(" : %s(X, Y, W, H, L) {\n", c); 01510 write_c(" _%s();\n", name()); 01511 write_c("}\n\n"); 01512 01513 // a constructor with just the size and label. The window manager will position the window 01514 write_c("%s::%s(int W, int H, const char *L)\n", name(), name()); 01515 write_c(" : %s(0, 0, W, H, L) {\n", c); 01516 write_c(" clear_flag(16);\n"); 01517 write_c(" _%s();\n", name()); 01518 write_c("}\n\n"); 01519 01520 // a constructor that takes size and label from the Fluid database 01521 write_c("%s::%s()\n", name(), name()); 01522 write_c(" : %s(0, 0, %d, %d, ", c, o->w(), o->h()); 01523 const char *cstr = label(); 01524 if (cstr) write_cstring(cstr); 01525 else write_c("0"); 01526 write_c(") {\n"); 01527 write_c(" clear_flag(16);\n"); 01528 write_c(" _%s();\n", name()); 01529 write_c("}\n\n"); 01530 01531 write_c("void %s::_%s() {\n", name(), name()); 01532 // write_c(" %s *w = this;\n", name()); 01533 } else { 01534 write_h("public:\n"); 01535 write_h(" %s(int X, int Y, int W, int H, const char *L = 0);\n", name()); 01536 01537 write_c("%s::%s(int X, int Y, int W, int H, const char *L)\n", name(), name()); 01538 if (wc_relative) 01539 write_c(" : %s(0, 0, W, H, L) {\n", c); 01540 else 01541 write_c(" : %s(X, Y, W, H, L) {\n", c); 01542 } 01543 01544 // write_c(" %s *o = this;\n", name()); 01545 01546 write_widget_code(); 01547 } 01548 01549 void Fl_Widget_Class_Type::write_code2() { 01550 write_extra_code(); 01551 if (wc_relative) write_c("%sposition(X, Y);\n", indent()); 01552 if (modal) write_c("%sset_modal();\n", indent()); 01553 else if (non_modal) write_c("%sset_non_modal();\n", indent()); 01554 if (!((Fl_Window*)o)->border()) write_c("%sclear_border();\n", indent()); 01555 if (xclass) { 01556 write_c("%sxclass(", indent()); 01557 write_cstring(xclass); 01558 write_c(");\n"); 01559 } 01560 write_c("%send();\n", indent()); 01561 if (((Fl_Window*)o)->resizable() == o) 01562 write_c("%sresizable(this);\n", indent()); 01563 write_c("}\n"); 01564 } 01565 01567 // live mode support 01568 01569 Fl_Widget *Fl_Window_Type::enter_live_mode(int) { 01570 Fl_Window *win = new Fl_Window(o->x(), o->y(), o->w(), o->h()); 01571 live_widget = win; 01572 if (live_widget) { 01573 copy_properties(); 01574 Fl_Type *n; 01575 for (n = next; n && n->level > level; n = n->next) { 01576 if (n->level == level+1) 01577 n->enter_live_mode(); 01578 } 01579 win->end(); 01580 } 01581 return live_widget; 01582 } 01583 01584 void Fl_Window_Type::leave_live_mode() { 01585 } 01586 01590 void Fl_Window_Type::copy_properties() { 01591 Fl_Widget_Type::copy_properties(); 01593 } 01594 01595 01596 // 01597 // End of "$Id: Fl_Window_Type.cxx 8089 2010-12-20 22:19:24Z matt $". 01598 //