toplevel.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:18k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: toplevel.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 21:14:14  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: toplevel.cpp,v 1000.1 2004/06/01 21:14:14 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Mike DiCuccio
  35.  *
  36.  * File Description:
  37.  *    CTopLevel -- top-level MDI window
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <gui/widgets/toplevel/toplevel.hpp>
  41. #include <FL/Fl.H>
  42. #include <FL/Fl_Box.H>
  43. #include <FL/Fl_Button.H>
  44. #include <FL/Fl_Group.H>
  45. #include <FL/Fl_Pixmap.H>
  46. #include <FL/Fl_Double_Window.H>
  47. #include <FL/fl_draw.H>
  48. #include "icon_tray.hpp"
  49. #include <algorithm>
  50. #include <math.h>
  51. BEGIN_NCBI_SCOPE
  52. //
  53. // static pixmaps
  54. // these are for the buttons in the system tray
  55. //
  56. static const char* sc_minimize_xpm[] = {
  57.     " 8 8 2 1",
  58.     "  c #111111",
  59.     "X c None",
  60.     "XXXXXXXX",
  61.     "XXXXXXXX",
  62.     "XXXXXXXX",
  63.     "XXXXXXXX",
  64.     "XXXXXXXX",
  65.     "XXXXXXXX",
  66.     "        ",
  67.     "        "
  68. };
  69. static const char* sc_maximize_xpm[] = {
  70.     " 8 8 2 1",
  71.     "  c #111111",
  72.     "X c None",
  73.     "        ",
  74.     "        ",
  75.     " XXXXXX ",
  76.     " XXXXXX ",
  77.     " XXXXXX ",
  78.     " XXXXXX ",
  79.     " XXXXXX ",
  80.     "        "
  81. };
  82. static const char* sc_close_xpm[] = {
  83.     "8 8 3 1",
  84.     "  c #111111",
  85.     ". c #616561",
  86.     "X c None",
  87.     " .XXXX. ",
  88.     ". .XX. .",
  89.     "X. .. .X",
  90.     "XX.  .XX",
  91.     "XX.  .XX",
  92.     "X. .. .X",
  93.     ". .XX. .",
  94.     " .XXXX. ",
  95. };
  96. //
  97. // static accessors - forwarded to CChildFrame
  98. //
  99. Fl_Boxtype CTopLevel::GetSysButtonBox(void)
  100. {
  101.     return CChildFrame::GetSysButtonBox();
  102. }
  103. void CTopLevel::SetSysButtonBox(Fl_Boxtype box)
  104. {
  105.     CChildFrame::SetSysButtonBox(box);
  106. }
  107. Fl_Color CTopLevel::GetSysButtonColor(void)
  108. {
  109.     return CChildFrame::GetSysButtonColor();
  110. }
  111. void CTopLevel::SetSysButtonColor(Fl_Color color)
  112. {
  113.     CChildFrame::SetSysButtonColor(color);
  114. }
  115. Fl_Color CTopLevel::GetSelectedColor(void)
  116. {
  117.     return CChildFrame::GetSelectedColor();
  118. }
  119. void CTopLevel::SetSelectedColor(Fl_Color color)
  120. {
  121.     CChildFrame::SetSelectedColor(color);
  122. }
  123. Fl_Font CTopLevel::GetTitleFont(void)
  124. {
  125.     return CChildFrame::GetTitleFont();
  126. }
  127. void CTopLevel::SetTitleFont(Fl_Font font)
  128. {
  129.     CChildFrame::SetTitleFont(font);
  130. }
  131. Fl_Color CTopLevel::GetTitleColor(void)
  132. {
  133.     return CChildFrame::GetTitleColor();
  134. }
  135. void CTopLevel::SetTitleColor(Fl_Color color)
  136. {
  137.     CChildFrame::SetTitleColor(color);
  138. }
  139. int CTopLevel::GetTitleSize(void)
  140. {
  141.     return CChildFrame::GetTitleSize();
  142. }
  143. void CTopLevel::SetTitleSize(int size)
  144. {
  145.     CChildFrame::SetTitleSize(size);
  146. }
  147. int CTopLevel::GetTitleAlign(void)
  148. {
  149.     return CChildFrame::GetTitleAlign();
  150. }
  151. void CTopLevel::SetTitleAlign(int align)
  152. {
  153.     CChildFrame::SetTitleAlign(align);
  154. }
  155. //
  156. //
  157. // class CTopLevel
  158. //
  159. //
  160. CTopLevel::CTopLevel(int x, int y, int wid, int ht, const char* label)
  161.     : Fl_Double_Window(x, y, wid, ht, label),
  162.       m_Selected(NULL),
  163.       m_IconTray(NULL),
  164.       m_MinimizeXPM(new Fl_Pixmap(sc_minimize_xpm)),
  165.       m_MaximizeXPM(new Fl_Pixmap(sc_maximize_xpm)),
  166.       m_CloseXPM   (new Fl_Pixmap(sc_close_xpm)),
  167.       m_LastChildX(0),
  168.       m_LastChildY(10)
  169. {
  170. }
  171. CTopLevel::~CTopLevel()
  172. {
  173.     delete m_MaximizeXPM;
  174.     delete m_MinimizeXPM;
  175.     delete m_CloseXPM;
  176. }
  177. //
  178. // add a child to our window
  179. //
  180. void CTopLevel::AddChild(CChild* child)
  181. {
  182.     if (!child) {
  183.         return;
  184.     }
  185.     //
  186.     // create a new frame to hold the child
  187.     //
  188.     child->hide();
  189.     // determine where this child will occur
  190.     m_LastChildX += CChildFrame::GetTitleBarHeight();
  191.     m_LastChildY += CChildFrame::GetTitleBarHeight();
  192.     if (m_LastChildX > w() - CChildFrame::GetTitleBarHeight()) {
  193.         m_LastChildX = 0;
  194.     }
  195.     if (m_LastChildY > h() - CChildFrame::GetTitleBarHeight()) {
  196.         m_LastChildY = 0;
  197.     }
  198.     //
  199.     // positions for our frame and subwidgets
  200.     //
  201.     // pseudoconstants constrolling our layout
  202.     const int button_w = 11 + Fl::box_dw(CChildFrame::GetSysButtonBox());
  203.     const int button_h = 11 + Fl::box_dh(CChildFrame::GetSysButtonBox());
  204.     const int x_step = button_w + 2;
  205.     CChildFrame::SetTitleBarHeight(max (CChildFrame::GetTitleSize() + 3,
  206.                                         button_h + 3));
  207.     // frame positions - dependent on our child window
  208.     Fl_Boxtype frame_box = FL_UP_BOX;
  209.     int frame_x = m_LastChildX;
  210.     int frame_y = m_LastChildY;
  211.     int frame_w = child->w() + Fl::box_dw(frame_box);
  212.     int frame_h = child->h() + Fl::box_dh(frame_box) +
  213.                   CChildFrame::GetTitleBarHeight();
  214.     // reposition our child relative to the new frame
  215.     child->position(frame_x + Fl::box_dx(frame_box),
  216.                     frame_y + Fl::box_dy(frame_box) +
  217.                     CChildFrame::GetTitleBarHeight());
  218.     // title group - encompasses the entire title bar
  219.     int title_group_x = 0 + Fl::box_dx(frame_box);
  220.     int title_group_y = 0 + Fl::box_dy(frame_box);
  221.     int title_group_w = frame_w - Fl::box_dw(frame_box) - 1;
  222.     int title_group_h = CChildFrame::GetTitleBarHeight();
  223.     // system buttons group
  224.     int sysbutt_x = 0 + frame_w - Fl::box_dw(frame_box) - x_step * 3 + 2;
  225.     int sysbutt_y = 0 + Fl::box_dy(frame_box);
  226.     int sysbutt_w = title_group_w - (sysbutt_x - 0) - 2;
  227.     int sysbutt_h = CChildFrame::GetTitleBarHeight();
  228.     // title label
  229.     int title_x = title_group_x;
  230.     int title_y = title_group_y;
  231.     int title_w = title_group_w - sysbutt_w - 5;
  232.     int title_h = title_group_h;
  233.     // offsets for buttons
  234.     int button_y = sysbutt_y + (sysbutt_h - button_h + 1) / 2;
  235.     // create the parent frame
  236.     CChildFrame* frame = new CChildFrame(frame_x, frame_y, frame_w, frame_h);
  237.     frame->box(frame_box);
  238.     // title bar
  239.     // this has a few system buttons in it
  240.     Fl_Group* title_bar =  new Fl_Group(title_group_x, title_group_y,
  241.                                         title_group_w, title_group_h);
  242.     title_bar->clear_visible_focus();
  243.     // spacer to prevent system buttons from resizing
  244.     // this also holds the title
  245.     Fl_Group* spacer = new Fl_Group(title_x, title_y, title_w, title_h,
  246.                                     child->label());
  247.     spacer->box       (FL_NO_BOX);
  248.     spacer->color     (CChildFrame::GetSelectedColor());
  249.     spacer->align     (CChildFrame::GetTitleAlign() | FL_ALIGN_INSIDE);
  250.     spacer->labelcolor(CChildFrame::GetTitleColor());
  251.     spacer->labelfont (CChildFrame::GetTitleFont());
  252.     spacer->labelsize (CChildFrame::GetTitleSize());
  253.     spacer->clear_visible_focus();
  254.     spacer->end();
  255.     title_bar->resizable(spacer);
  256.     // system buttons, grouped to prevent resize and to facilitate easier event
  257.     // screening
  258.     Fl_Group* sys_buttons = new Fl_Group(sysbutt_x, sysbutt_y,
  259.                                          sysbutt_w, sysbutt_h);
  260.     sys_buttons->box(FL_NO_BOX);
  261.     sys_buttons->clear_visible_focus();
  262.     // minimize button
  263.     Fl_Button* minimize = new Fl_Button(sysbutt_x, button_y,
  264.                                         button_w, button_h);
  265.     minimize->image   (m_MinimizeXPM);
  266.     minimize->box     (CChildFrame::GetSysButtonBox());
  267.     minimize->color   (CChildFrame::GetSysButtonColor());
  268.     minimize->tooltip ("Minimize this window");
  269.     minimize->callback((Fl_Callback*)&CTopLevel::x_StaticCB_Minimize, this);
  270.     minimize->clear_visible_focus();
  271.     // maximize button
  272.     Fl_Button* maximize = new Fl_Button(sysbutt_x + x_step, button_y,
  273.                                         button_w, button_h);
  274.     maximize->image   (m_MaximizeXPM);
  275.     maximize->box     (CChildFrame::GetSysButtonBox());
  276.     maximize->color   (CChildFrame::GetSysButtonColor());
  277.     maximize->tooltip ("Maximize this window");
  278.     maximize->callback((Fl_Callback*)&CTopLevel::x_StaticCB_Maximize, this);
  279.     maximize->clear_visible_focus();
  280.     // close button
  281.     Fl_Button* close = new Fl_Button(sysbutt_x + x_step * 2, button_y,
  282.                                      button_w, button_h);
  283.     close->image   (m_CloseXPM);
  284.     close->box     (CChildFrame::GetSysButtonBox());
  285.     close->color   (CChildFrame::GetSysButtonColor());
  286.     close->tooltip ("Hide this window");
  287.     close->callback((Fl_Callback*)&CTopLevel::x_StaticCB_Close, this);
  288.     close->clear_visible_focus();
  289.     // end sys group
  290.     sys_buttons->end();
  291.     // end title bar
  292.     title_bar->end();
  293.     // end frame
  294.     frame->end();
  295.     add(*frame);
  296.     // create a frame manager class
  297.     frame->m_TitleBar   = title_bar;
  298.     frame->m_SysButtons = sys_buttons;
  299.     frame->m_Title      = spacer;
  300.     frame->Attach(child);
  301.     m_Children.push_back(frame);
  302.     frame->show();
  303.     child->show();
  304.     // and select our current frame
  305.     x_SetSelected(frame);
  306. }
  307. void CTopLevel::x_SetSelected(CChildFrame* frame)
  308. {
  309.     if (m_Selected) {
  310.         m_Selected->m_Title->box(FL_NO_BOX);
  311.         m_Selected->m_Title->redraw();
  312.     }
  313.     // determine our new selection
  314.     // if the selection is NULL and we have kids, we automatically select the
  315.     // last child ( = topmost)
  316.     m_Selected = frame;
  317.     if ( !m_Selected ) {
  318.         return;
  319.     }
  320.     // cycle the child to the end of the array of children
  321.     // this has the effect of raising the window and provides us with correct
  322.     // selection order
  323.     TChildren::iterator iter =
  324.         std::find(m_Children.begin(), m_Children.end(), m_Selected);
  325.     if (iter != m_Children.end()) {
  326.         CChildFrame* frame = *iter;
  327.         m_Children.erase(iter);
  328.         m_Children.push_back(frame);
  329.     }
  330.     // we re-add the frame
  331.     // this keeps the child array in sync with m_Children
  332.     add(m_Selected);
  333.     //m_Selected->hide();
  334.     m_Selected->show();
  335.     // make sure the title bar is correctly highlighted
  336.     m_Selected->m_Title->box(FL_ROUNDED_BOX);
  337.     m_Selected->m_Title->redraw();
  338. }
  339. int CTopLevel::handle(int event)
  340. {
  341.     switch (event) {
  342.         //
  343.         // FL_PUSH: handle mouse click events
  344.         // We need to distinguish a few things here:
  345.         //
  346.         // title bar single click - begin drag or select new child
  347.         // frame border single click - begin resize or select new child
  348.         // system buttons single click - select new child and pass on to button
  349.         //
  350.     case FL_PUSH:
  351.         if ( !m_Selected  ||  !Fl::event_inside(m_Selected) )  {
  352.              // try to select another child
  353.              // we scan in reverse, as this scans top-most down
  354.              TChildren::reverse_iterator start(m_Children.end());
  355.              TChildren::reverse_iterator stop (m_Children.begin());
  356.              for ( ;  start != stop;  ++start) {
  357.                  CChildFrame* child = *start;
  358.                  if (child->visible()  &&  Fl::event_inside(child)) {
  359.                      x_SetSelected(child);
  360.                      if (Fl::event_inside(child->m_SysButtons)) {
  361.                          // we select the window, but let the child process
  362.                          // the event
  363.                          break;
  364.                      }
  365.                      // claim the event for our own, don't pass on to children
  366.                      // or parent
  367.                      return 1;
  368.                  }
  369.              }
  370.         }
  371.         break;
  372.     default:
  373.         break;
  374.     }
  375.     return Fl_Double_Window::handle(event);
  376. }
  377. void CTopLevel::resize(int x, int y, int w, int h)
  378. {
  379.     if (m_Selected  &&  m_Selected->GetMaximized()) {
  380.         m_Selected->resize(0, 0, w, h);
  381.     }
  382.     Fl_Double_Window::resize(x, y, w, h);
  383. }
  384. //
  385. // Force all windows to cascade
  386. //
  387. void CTopLevel::Cascade(void)
  388. {
  389.     if (m_Selected  &&  m_Selected->GetMaximized()) {
  390.         return;
  391.     }
  392.     int pos_x = 0;
  393.     int pos_y = 0;
  394.     int step  = CChildFrame::GetTitleBarHeight();
  395.     NON_CONST_ITERATE (TChildren, iter, m_Children) {
  396.         CChildFrame* frame = *iter;
  397.         if ( !frame->visible()  ||  frame->GetMinimized() ) {
  398.             continue;
  399.         }
  400.         frame->position(pos_x, pos_y);
  401.         pos_x += step;
  402.         pos_y += step;
  403.         if (pos_x > w() - 100) {
  404.             pos_x = 0;
  405.         }
  406.         if (pos_y > h() - step) {
  407.             pos_y = 0;
  408.         }
  409.     }
  410. }
  411. void CTopLevel::Tile(void)
  412. {
  413.     if (m_Children.size() == 0  ||
  414.         (m_Selected  &&  m_Selected->GetMaximized())) {
  415.         return;
  416.     }
  417.     // firstly, count the number of kids we evaluate
  418.     int kids = 0;
  419.     ITERATE (TChildren, iter, m_Children) {
  420.         const CChildFrame* frame = *iter;
  421.         if ( !frame->visible()  ||  frame->GetMinimized() ) {
  422.             continue;
  423.         }
  424.         ++kids;
  425.     }
  426.     // determine the optimal number of rows and columns
  427.     float s = (float)::sqrt((double)kids);
  428.     int kids_w = (int)s;
  429.     int kids_h = kids_w;
  430.     if (kids_w < s) {
  431.         ++kids_w;
  432.     }
  433.     while (kids_w * kids_h < kids) {
  434.         ++kids_h;
  435.     }
  436.     int child_width  = w() / kids_w;
  437.     int child_height = h() / kids_h;
  438.     for (TChildren::size_type i = 0, j = 0;  i < m_Children.size();  ++i) {
  439.         CChildFrame* frame = m_Children[i];
  440.         if ( !frame->visible()  ||  frame->GetMinimized() ) {
  441.             continue;
  442.         }
  443.         int pos_x = (j % kids_w) * child_width;
  444.         int pos_y = (j / kids_w) * child_height;
  445.         ++j;
  446.         frame->resize(pos_x, pos_y, child_width, child_height);
  447.     }
  448. }
  449. //
  450. // Window Maximization
  451. //
  452. void CTopLevel::x_Maximize(void)
  453. {
  454.     if ( !m_Selected ) {
  455.         return;
  456.     }
  457.     if ( m_Selected->GetMaximized()) {
  458.         m_Selected->m_State = CChildFrame::eNormal;
  459.         m_Selected->resize(m_Selected->m_SavedPos[0],
  460.                            m_Selected->m_SavedPos[1],
  461.                            m_Selected->m_SavedPos[2],
  462.                            m_Selected->m_SavedPos[3]);
  463.         // must redraw the whole thing
  464.         redraw();
  465.     } else {
  466.         m_Selected->m_SavedPos[0] = m_Selected->x();
  467.         m_Selected->m_SavedPos[1] = m_Selected->y();
  468.         m_Selected->m_SavedPos[2] = m_Selected->w();
  469.         m_Selected->m_SavedPos[3] = m_Selected->h();
  470.         m_Selected->m_State = CChildFrame::eMaximized;
  471.         m_Selected->resize(0, 0, w(), h());
  472.         m_Selected->redraw();
  473.     }
  474. }
  475. void CTopLevel::x_StaticCB_Maximize(Fl_Widget* w, void* data)
  476. {
  477.     if ( !data ) {
  478.         return;
  479.     }
  480.     CTopLevel* toplevel = reinterpret_cast<CTopLevel*> (data);
  481.     toplevel->x_Maximize();
  482. }
  483. //
  484. // Window Minimization / iconification
  485. //
  486. void CTopLevel::x_Minimize(void)
  487. {
  488.     //FIXME: implement this
  489. #if 0
  490.     if ( !m_Selected ) {
  491.         return;
  492.     }
  493.     if ( !m_IconTray ) {
  494.         m_IconTray = new CIconTray(0, 0, w(), h());
  495.         m_IconTray->box(FL_NO_BOX);
  496.         insert(*m_IconTray, 0);
  497.     }
  498.     m_IconTray->Add(m_Selected);
  499.     redraw();
  500. #endif
  501. }
  502. void CTopLevel::x_StaticCB_Minimize(Fl_Widget*, void* data)
  503. {
  504.     CTopLevel* frame = reinterpret_cast<CTopLevel*> (data);
  505.     if (frame) {
  506.         frame->x_Minimize();
  507.     }
  508. }
  509. //
  510. // Window "close"
  511. // This is really hide - true deletion is handled elsewhere
  512. //
  513. void CTopLevel::x_Close(void)
  514. {
  515.     if ( !m_Selected ) {
  516.         return;
  517.     }
  518.     m_Selected->hide();
  519. }
  520. void CTopLevel::x_StaticCB_Close(Fl_Widget*, void* data)
  521. {
  522.     if ( !data ) {
  523.         return;
  524.     }
  525.     CTopLevel* toplevel = reinterpret_cast<CTopLevel*> (data);
  526.     toplevel->x_Close();
  527. }
  528. END_NCBI_SCOPE
  529. /*
  530.  * ===========================================================================
  531.  * $Log: toplevel.cpp,v $
  532.  * Revision 1000.1  2004/06/01 21:14:14  gouriano
  533.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9
  534.  *
  535.  * Revision 1.9  2004/05/21 22:27:56  gorelenk
  536.  * Added PCH ncbi_pch.hpp
  537.  *
  538.  * Revision 1.8  2004/05/03 13:23:58  dicuccio
  539.  * gui/utils --> gui/objutils where needed
  540.  *
  541.  * Revision 1.7  2003/07/25 13:38:44  dicuccio
  542.  * Minor clean-up in issuing redraw events
  543.  *
  544.  * Revision 1.6  2003/03/25 13:17:50  dicuccio
  545.  * Fix (hopefully) MIPS compile - be explicit about which sqrt() is being used
  546.  *
  547.  * Revision 1.5  2003/03/17 19:48:52  dicuccio
  548.  * Fixed xpm specifications to make WorkShop compiler happy.
  549.  *
  550.  * Revision 1.4  2003/03/17 14:55:41  dicuccio
  551.  * Lots of clean-up.  Fixed memory leaks in test program; added more explicit
  552.  * destruction pathway to support integration into Genome Workbench.  Added
  553.  * explicit calls to cascade / tile widgets in a toplevel workspace.
  554.  *
  555.  * Revision 1.3  2003/03/07 18:14:58  dicuccio
  556.  * Code clean-up.  Added missing accessors for look-n-feel statics; aligned
  557.  * accessors in code
  558.  *
  559.  * Revision 1.2  2003/03/07 17:49:25  dicuccio
  560.  * Small clean-ups.  Added description for each class.
  561.  *
  562.  * Revision 1.1  2003/03/07 17:36:08  dicuccio
  563.  * Initial revision
  564.  *
  565.  * ===========================================================================
  566.  */