nux-1.14.0
ComboBoxComplex.cpp
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "Nux.h"
00024 
00025 #include "ComboBoxComplex.h"
00026 #include "PopUpWindow.h"
00027 #include "MenuPage.h"
00028 #include "TableItem.h"
00029 #include "ListControl.h"
00030 #include "ActionItem.h"
00031 #include "PropertyList.h"
00032 #include "WindowCompositor.h"
00033 
00034 namespace nux
00035 {
00036 
00037   ComboBoxComplex::ComboBoxComplex (NUX_FILE_LINE_DECL)
00038     :   AbstractComboBox (NUX_FILE_LINE_PARAM)
00039   {
00040     m_ListBox       = 0;
00041     m_PopupWindow   = 0;
00042     m_Layout        = 0;
00043 
00044     InitializeLayout();
00045     InitializeWidgets();
00046   }
00047 
00048   ComboBoxComplex::~ComboBoxComplex()
00049   {
00050     m_PopupWindow->Dispose ();
00051   }
00052 
00053   void ComboBoxComplex::InitializeWidgets()
00054   {
00055     // Set Signals
00056     _combo_box_opening_area->mouse_down.connect (sigc::mem_fun (this, &ComboBoxComplex::RecvMouseDown) );
00057     _combo_box_opening_area->mouse_up.connect (sigc::mem_fun (this, &ComboBoxComplex::RecvMouseUp) );
00058     _combo_box_opening_area->mouse_drag.connect (sigc::mem_fun (this, &ComboBoxComplex::RecvMouseDrag) );
00059 
00060     _combo_box_area->mouse_down.connect (sigc::mem_fun (this, &ComboBoxComplex::RecvMouseDown) );
00061     _combo_box_area->mouse_up.connect (sigc::mem_fun (this, &ComboBoxComplex::RecvMouseUp) );
00062     _combo_box_area->mouse_drag.connect (sigc::mem_fun (this, &ComboBoxComplex::RecvMouseDrag) );
00063 
00064     // Set Geometry
00065     _combo_box_opening_area->SetGeometry (Geometry (0, 0, 20, DEFAULT_WIDGET_HEIGHT) );
00066     _combo_box_opening_area->SetMinimumSize (20, DEFAULT_WIDGET_HEIGHT);
00067 
00068     _combo_box_area->SetMinimumSize (2 * DEFAULT_WIDGET_WIDTH, PRACTICAL_WIDGET_HEIGHT);
00069     _combo_box_area->SetGeometry (Geometry (0, 0, 3 * DEFAULT_WIDGET_WIDTH, PRACTICAL_WIDGET_HEIGHT) );
00070 
00071     m_ListBox->UsedForComboBox (true);
00072 
00073     // Remove horizontal scrollbar
00074     m_ListBox->EnableHorizontalScrollBar (false);
00075     // Force the list size to respect the size of its layout.
00076     m_ListBox->SetSizeMatchContent (true);
00077     m_ListBox->SetViewContentLeftMargin (0);
00078     m_ListBox->SetViewContentRightMargin (0);
00079     m_ListBox->SetViewContentTopMargin (0);
00080     m_ListBox->SetViewContentBottomMargin (0);
00081     m_ListBox->SetMouseOverColor (Color (0xff868686) );
00082     m_ListBox->SetRowColorEven (Color (0xff999999) );
00083     m_ListBox->SetRowColorOdd (Color (0xff999999) );
00084     m_ListBox->EnableMouseOverColor (true);
00085     m_ListBox->ShowHorizontalSeparationLine (false);
00086     m_ListBox->SetMaximumHeight (200);
00087 
00088     m_ListBox->sigTableItemSelected.connect (sigc::mem_fun (this, &ComboBoxComplex::RecvSigActionTriggered) );
00089     m_ListBox->SetGeometry (Geometry (0, 0, 100, 400) );
00090     m_Layout->AddView (m_ListBox, 1, eAbove, eFull);
00091     // Setting the layout stretch factor to 0 forces the list TableCtrl to have always use its minimum width.
00092     // This is how the PopupWindow width is controlled. SetPopupWidth define the minimum width of the TableCtrl.
00093     // Because m_Layout(a HLayout) has a stretch factor of 0, it will force the m_ListBox to its minimum width.
00094     m_Layout->SetStretchFactor (0);
00095     m_PopupWindow->SetLayout (m_Layout);
00096 
00097     // Call PopupWindow::SetWindowSizeMatchLayout with TRUE as argument and the popupWindow will preserve the size of its layout.
00098     m_PopupWindow->SetWindowSizeMatchLayout (true);
00099   }
00100 
00101   void ComboBoxComplex::InitializeLayout()
00102   {
00103     m_Layout        = new HLayout(NUX_TRACKER_LOCATION);
00104     m_ListBox       = new ListControl(false);
00105     m_PopupWindow   = new PopUpWindow();
00106   }
00107 
00108   long ComboBoxComplex::ProcessEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00109   {
00110     long ret = TraverseInfo;
00111 
00112     ret = _combo_box_opening_area->OnEvent (ievent, ret, ProcessEventInfo);
00113     ret = _combo_box_area->OnEvent (ievent, ret, ProcessEventInfo);
00114 
00115     if (ievent.e_event == NUX_MOUSE_RELEASED)
00116     {
00117       // Cancel m_IsOpeningMenu in case it hasn't been changed in _combo_box_opening_area->OnEvent or _combo_box_area->OnEvent.
00118       // This can happen if the table area of the m_ListBox get the NUX_MOUSE_RELEASED event first and sets
00119       // TraverseInfo to MouseEventSolved.
00120       if (m_IsOpeningMenu == true)
00121         m_IsOpeningMenu = false;
00122     }
00123 
00124     if (ievent.e_event == NUX_MOUSE_PRESSED)
00125     {
00126       // The mouse down can also happen the first time to initiate the opening of the menu. That is why we need
00127       // the flag m_IsOpeningMenu;
00128       bool mouse_down_on_menu_item = false;
00129 
00130       if (m_MenuIsActive == true)
00131       {
00132         // The menu is opened.
00133         // Did we hit the button (the one with the arrow pointing down) or did we hit the rest
00134         // of the Combo area?
00135         if (_combo_box_opening_area->IsMouseInside() || _combo_box_area->IsMouseInside() )
00136           mouse_down_on_menu_item = true;
00137 
00138         if (mouse_down_on_menu_item == false)
00139         {
00140           // We did not hit the permanently visible area of the combo widget.
00141           // Did we hit the area of the popup menu?
00142           Geometry window_geometry = m_PopupWindow->GetGeometry();
00143 
00144           if (!window_geometry.IsPointInside (ievent.GetX(), ievent.GetY() ) && (m_IsOpeningMenu == false) )
00145           {
00146             m_PopupWindow->Hide();
00147             m_MenuIsActive = false;
00148           }
00149 
00150           //m_MenuIsActive = false;
00151         }
00152         else
00153         {
00154           if (m_IsOpeningMenu == false)
00155           {
00156             m_PopupWindow->Hide();
00157             m_MenuIsActive = false;
00158           }
00159         }
00160       }
00161     }
00162 
00163     ret = PostProcessEvent2 (ievent, ret, ProcessEventInfo);
00164     return ret;
00165   }
00166 
00167   void ComboBoxComplex::AddItem (TableItem *item)
00168   {
00169     if (item == 0)
00170       return;
00171 
00172     if (m_ListBox && (m_ListBox->GetNumRootChild() == 0) )
00173     {
00174       // The first element added is the element featured on the combobox when it is closed.
00175       m_ListBox->setTableItems (item);
00176       m_SelectedTreeNode = item;
00177       _combo_box_area->SetBaseString (m_SelectedTreeNode->GetName() );
00178     }
00179     else if (m_ListBox)
00180     {
00181       m_ListBox->setTableItems (item);
00182     }
00183   }
00184 
00185   void ComboBoxComplex::RemoveItem (TableItem *item)
00186   {
00187 
00188   }
00189 
00190   void ComboBoxComplex::RemoveAllItem()
00191   {
00192 
00193   }
00194 
00195   void ComboBoxComplex::RecvMouseDown (int x, int y, unsigned long button_flags, unsigned long key_flags)
00196   {
00197     if (m_MenuIsActive == false)
00198     {
00199       // Open the Menu
00200       m_MenuIsActive = true;
00201       m_IsOpeningMenu = true;
00202 
00203       m_PopupWindow->SetBaseXY (_combo_box_area->GetBaseX(), _combo_box_area->GetBaseY() + _combo_box_area->GetBaseHeight() );
00204       m_PopupWindow->Show();
00205 
00206       if (m_ListBox)
00207       {
00208         m_ListBox->ResetItems();
00209       }
00210 
00211     }
00212     else
00213     {
00214       // If the mouse up that follows happen inside the area, then it is going to close the menu.
00215       m_IsOpeningMenu = false;
00216     }
00217 
00218     QueueDraw();
00219   }
00220 
00221   void ComboBoxComplex::RecvMouseUp (int x, int y, unsigned long button_flags, unsigned long key_flags)
00222   {
00223     if (m_MenuIsActive)
00224     {
00225       if (_combo_box_area->IsMouseInside() || _combo_box_opening_area->IsMouseInside() )
00226       {
00227         if (m_IsOpeningMenu == false)
00228         {
00229           // close the Menu that is Open
00230           //m_CurrentMenu->StopMenu(0, 0);
00231           m_MenuIsActive = false;
00232         }
00233         else
00234         {
00235           // The MousePress before this MouseRelease, caused the Menu to open.
00236           // Set m_IsOpeningMenu so the next mouse release will close the menu.
00237           m_IsOpeningMenu = false;
00238           m_MenuIsActive = true;
00239         }
00240       }
00241       else
00242       {
00243         int row, column;
00244         TableItem *item = 0;
00245         m_ListBox->GetBaseX();
00246         m_ListBox->GetBaseY();
00247         int X = x + _combo_box_area->GetBaseX() - m_PopupWindow->GetBaseX() - m_ListBox->GetBaseX();
00248         int Y = y + _combo_box_area->GetBaseY() - m_PopupWindow->GetBaseY() - m_ListBox->GetBaseY();
00249         m_ListBox->FindItemUnderPointer (X, Y, &item, row, column);
00250 
00251         if (item)
00252         {
00253           RecvSigActionTriggered (*m_ListBox, *item, row, column);
00254         }
00255         else
00256         {
00257           m_MenuIsActive = false;
00258           m_PopupWindow->Hide();
00259         }
00260 
00261 //            bool hit_inside_a_menu = false;
00262 //            bool b = m_CurrentMenu->TestMouseUp(x, y, button_flags, hit_inside_a_menu);
00263 //            if(b || (hit_inside_a_menu == false))
00264 //            {
00265 //                RecvSigTerminateMenuCascade();
00266 //                m_MenuIsActive = false;
00267 //                m_PopupWindow->Hide();
00268 //            }
00269       }
00270     }
00271 
00272     QueueDraw();
00273   }
00274 
00275   void ComboBoxComplex::RecvMouseDrag (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
00276   {
00277 //    int row, column;
00278 //    TableItem* item = 0;
00279 //    int X = x + _combo_box_area->GetX() - m_PopupWindow->GetX() - m_ListBox->GetX();
00280 //    int Y = y + _combo_box_area->GetY() - m_PopupWindow->GetY() - m_ListBox->GetY();
00281 //    m_ListBox->FindItemUnderPointer(X, Y, &item, row, column);
00282 //    m_ListBox->HighlightItem(row, column);
00283 
00284     if (GetWindowCompositor().GetCurrentEvent() )
00285     {
00286       m_PopupWindow->ProcessEvent (const_cast<IEvent &> (*GetWindowCompositor().GetCurrentEvent() ), 0, 0);
00287     }
00288   }
00289 
00290   void ComboBoxComplex::RecvSigActionTriggered (TableCtrl &table, TableItem &item, unsigned int row, unsigned int column)
00291   {
00292     m_MenuIsActive = false;
00293     //m_CurrentMenu->StopMenu();
00294 
00295     m_IsOpeningMenu = false;
00296 
00297     m_SelectedTreeNode = &item;
00298     _combo_box_area->SetBaseString (m_SelectedTreeNode->GetName() );
00299     sigSelectedItem.emit (item);
00300 
00301     m_PopupWindow->Hide();
00302     QueueDraw();
00303     // You can do something if you want with the menu* and the action*
00304   }
00305 
00306   void ComboBoxComplex::RecvSigTerminateMenuCascade()
00307   {
00308     //m_MenuIsActive = false;
00309     //m_CurrentMenu->StopMenu();
00310     m_IsOpeningMenu = false;
00311   }
00312 
00313   void ComboBoxComplex::SetPopupWindowSize (unsigned int width, unsigned int height)
00314   {
00315     m_ListBox->SetMaximumSize (width, height);
00316   }
00317 
00318   void ComboBoxComplex::SetPopupWidth (unsigned int width)
00319   {
00320     m_ListBox->SetMinimumWidth (width);
00321   }
00322 
00323   long ComboBoxComplex::PostLayoutManagement (long LayoutResult)
00324   {
00325     View::PostLayoutManagement (LayoutResult);
00326     Geometry geo = GetGeometry();
00327 
00328     // If we call m_ListBox->SetSizeMatchContent(false) in the constructor, then the m_ListBox will use its minimum height because
00329     // m_Layout has a stretch factor of 0 and the m_ListBox height is set to eFull;
00330     m_ListBox->SetMinimumHeight (60);
00331 //    m_ListBox->SetMaximumHeight(300);
00332     m_ListBox->SetMinimumWidth (GetBaseWidth() );
00333 
00334     return LayoutResult;
00335   }
00336 
00337 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends