nux-1.14.0
|
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 }