Back to index

nux  3.0.0
BaseWindow.cpp
Go to the documentation of this file.
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 #include "Nux.h"
00023 
00024 #include "NuxGraphics/GLTextureResourceManager.h"
00025 
00026 #include "Layout.h"
00027 #include "HLayout.h"
00028 #include "WindowCompositor.h"
00029 #include "BaseWindow.h"
00030 #include "TextEntry.h"
00031 
00032 namespace nux
00033 {
00034 
00035   NUX_IMPLEMENT_OBJECT_TYPE(BaseWindow);
00036 
00037   const int SizeGripWidth = 20;
00038   const int SizeGripHeight = 20;
00039   const int TitleBarHeight = 20;
00040 
00041   /*
00042       Elements inside the Window have coordinates based on the top-left corner of the window.
00043       This is true whether we are drawing or computing the layout. When computing the layout, use x_root and y_root to
00044       pass the top-left corner position of the window. When drawing, make a similar adjustment.
00045   */
00046 
00047   BaseWindow::BaseWindow(const char *WindowName, NUX_FILE_LINE_DECL)
00048     : View(NUX_FILE_LINE_PARAM)
00049     , _paint_layer(new ColorLayer(Color(0xFF707070)))
00050     , _opacity(1.0f)
00051   {
00052     premultiply = true;
00053     _name = WindowName;
00054     _child_need_redraw = true;
00055     m_TopBorder = 0;
00056     m_Border = 0;
00057     _size_match_layout = false;
00058     _is_visible = false;
00059     _is_modal = false;
00060 #if defined(NUX_OS_LINUX)
00061     m_input_window_enabled = false;
00062     m_input_window = 0;
00063 #endif
00064     m_layout = 0;
00065     m_configure_notify_callback = NULL;
00066     m_configure_notify_callback_data = NULL;
00067     _entering_visible_state = false;
00068     _entering_hidden_state = false;
00069     _enter_focus_input_area = NULL;
00070     accept_key_nav_focus_ = false;
00071 
00072     SetAcceptKeyNavFocusOnMouseDown(false);
00073 
00074     // Should be at the end of the constructor
00075     GetWindowThread()->GetWindowCompositor().RegisterWindow(this);
00076 
00077     SetMinimumSize(1, 1);
00078     SetGeometry(Geometry(100, 100, 320, 200));
00079   }
00080 
00081   BaseWindow::~BaseWindow()
00082   {
00083     if (_enter_focus_input_area)
00084     {
00085       _enter_focus_input_area->UnReference();
00086     }
00087 
00088 #if defined(NUX_OS_LINUX)
00089     if (m_input_window)
00090       delete m_input_window;
00091 #endif
00092   }
00093 
00094   Area* BaseWindow::FindAreaUnderMouse(const Point& mouse_position, NuxEventType event_type)
00095   {
00096     bool mouse_inside = TestMousePointerInclusionFilterMouseWheel(mouse_position, event_type);
00097 
00098     if (mouse_inside == false)
00099       return NULL;
00100 
00101     if (m_layout)
00102     {
00103       nuxAssert(m_layout->IsLayout());
00104       Area* found_area = m_layout->FindAreaUnderMouse(mouse_position, event_type);
00105       if (found_area)
00106         return found_area;
00107     }
00108 
00109     if ((event_type == NUX_MOUSE_WHEEL) && (!AcceptMouseWheelEvent()))
00110       return NULL;
00111     return this;
00112   }
00113 
00114   void BaseWindow::Draw(GraphicsEngine &graphics_engine, bool force_draw)
00115   {
00116     Geometry base = GetGeometry();
00117     // The elements position inside the window are referenced to top-left window corner. So bring base to(0, 0).
00118     base.SetX(0);
00119     base.SetY(0);
00120     graphics_engine.PushClippingRectangle(base);
00121 
00122     GetPainter().PushDrawLayer(graphics_engine, base, _paint_layer.get());
00123 
00124     GetPainter().PopBackground();
00125     graphics_engine.PopClippingRectangle();
00126   }
00127 
00128   void BaseWindow::DrawContent(GraphicsEngine &graphics_engine, bool force_draw)
00129   {
00130 
00131     Geometry base = GetGeometry();
00132     // The elements position inside the window are referenced to top-left window corner. So bring base to(0, 0).
00133     base.SetX(0);
00134     base.SetY(0);
00135 
00136 
00137     GetPainter().PushLayer(graphics_engine, base, _paint_layer.get());
00138 
00139     if (m_layout)
00140     {
00141       graphics_engine.PushClippingRectangle(base);
00142       m_layout->ProcessDraw(graphics_engine, force_draw);
00143       graphics_engine.PopClippingRectangle();
00144     }
00145 
00146     GetPainter().PopBackground();
00147   }
00148 
00149   void BaseWindow::PostDraw(GraphicsEngine &graphics_engine, bool force_draw)
00150   {
00151 
00152   }
00153 
00154   void BaseWindow::SetConfigureNotifyCallback(ConfigureNotifyCallback Callback, void *Data)
00155   {
00156     m_configure_notify_callback = Callback;
00157     m_configure_notify_callback_data = Data;
00158   }
00159 
00160   Layout* BaseWindow::GetLayout()
00161   {
00162     return m_layout;
00163   }
00164 
00165   bool BaseWindow::SetLayout(Layout *layout)
00166   {
00167     if (View::SetLayout(layout) == false)
00168       return false;
00169 
00170     m_layout = layout;
00171     Geometry geo = GetGeometry();
00172     Geometry layout_geo = Geometry(geo.x + m_Border, geo.y + m_TopBorder,
00173                                     geo.GetWidth() - 2 * m_Border, geo.GetHeight() - m_Border - m_TopBorder);
00174     m_layout->SetGeometry(layout_geo);
00175 
00176     // When this call returns the layout computation is done.
00177     ComputeContentSize();
00178     // or use
00179     //GetWindowThread()->QueueObjectLayout(m_layout);
00180 
00181     return true;
00182   }
00183 
00184   // Get a change to do any work on an element.
00185   // Here we need to position the header by hand because it is not under the control of vlayout.
00186   void BaseWindow::PreLayoutManagement()
00187   {
00188     Geometry geo = GetGeometry();
00189 
00190     if (m_configure_notify_callback)
00191     {
00192       (*m_configure_notify_callback)(GetGraphicsDisplay()->GetWindowWidth(), GetGraphicsDisplay()->GetWindowHeight(), geo, m_configure_notify_callback_data);
00193 
00194       if (geo.IsNull())
00195       {
00196         nuxDebugMsg("[BaseWindow::PreLayoutManagement] Received an invalid Geometry.");
00197         geo = GetGeometry();
00198       }
00199       else
00200       {
00201         Area::SetGeometry(geo);
00202         // Get the geometry adjusted with respect to min and max dimension of this area.
00203         geo = GetGeometry();
00204       }
00205     }
00206 
00207     if (m_layout)
00208     {
00209       Geometry layout_geo = Geometry(m_Border, m_TopBorder,
00210                                       geo.GetWidth() - 2 * m_Border, geo.GetHeight() - m_Border - m_TopBorder);
00211 
00212       if (IsSizeMatchContent())
00213         m_layout->SetGeometry(Geometry(0, 0, 1, 1));
00214       else
00215         m_layout->SetGeometry(layout_geo);
00216     }
00217   }
00218 
00219 // Get a change to do any work on an element.
00220 // Here we need to position the header by hand because it is not under the control of vlayout.
00221   long BaseWindow::PostLayoutManagement(long LayoutResult)
00222   {
00223     if (IsSizeMatchContent() && m_layout)
00224     {
00225       Geometry layout_geometry = m_layout->GetGeometry();
00226 
00227       Geometry WindowGeometry = Geometry(GetGeometry().x,
00228                                           GetGeometry().y,
00229                                           layout_geometry.GetWidth() + 2 * m_Border,
00230                                           layout_geometry.GetHeight() + m_Border + m_TopBorder);
00231 
00232       Area::SetGeometry(WindowGeometry);
00233     }
00234 
00235     // A BaseWindow must kill the result of the management and pass it to the parent Layout.
00236     return (eCompliantHeight | eCompliantWidth);
00237     //return result;
00238   }
00239 
00240 // Get a change to do any work on an element.
00241 // Here we need to position the header by hand because it is not under the control of vlayout.
00242   void BaseWindow::ComputeContentPosition(float offsetX, float offsetY)
00243   {
00244 
00245   }
00246 
00247   #if defined(NUX_OS_LINUX)
00248   void BaseWindow::EnableInputWindow(bool        b,
00249                                       const char* title,
00250                                       bool        take_focus,
00251                                       bool        override_redirect)
00252   {
00253     if (b)
00254     {
00255       if (m_input_window == 0)
00256         m_input_window = new XInputWindow(title, take_focus, override_redirect);
00257 
00258       m_input_window->Show();
00259       m_input_window->SetGeometry(GetGeometry());
00260       m_input_window_enabled = true;
00261     }
00262     else
00263     {
00264       if (m_input_window)
00265         m_input_window->Hide();
00266       m_input_window_enabled = false;
00267     }
00268   }
00269 
00270   bool BaseWindow::InputWindowEnabled()
00271   {
00272     return m_input_window_enabled;
00273   }
00274 
00275   void BaseWindow::InputWindowEnableStruts(bool enable)
00276   {
00277     if (m_input_window)
00278       m_input_window->EnableStruts(enable);
00279   }
00280 
00281   bool BaseWindow::InputWindowStrutsEnabled()
00282   {
00283     return m_input_window_enabled && m_input_window->StrutsEnabled();
00284   }
00285 
00286   void BaseWindow::InputWindowEnableOverlayStruts(bool enable)
00287   {
00288     if (m_input_window)
00289       m_input_window->EnableOverlayStruts(enable);
00290   }
00291 
00292   bool BaseWindow::InputWindowOverlayStrutsEnabled()
00293   {
00294     return m_input_window && m_input_window->OverlayStrutsEnabled();
00295   }
00296 
00297   void BaseWindow::SetInputFocus()
00298   {
00299     if (m_input_window)
00300       m_input_window->SetInputFocus();
00301   }
00302 
00303   Window BaseWindow::GetInputWindowId()
00304   {
00305     if (m_input_window)
00306       return m_input_window->GetWindow();
00307     else
00308       return 0;
00309   }
00310 
00311   #endif
00312 
00313   void BaseWindow::SetGeometry(const Geometry &geo)
00314   {
00315     Area::SetGeometry(geo);
00316 
00317     #if defined(NUX_OS_LINUX)
00318     if (m_input_window)
00319       m_input_window->SetGeometry(geo);
00320     #endif
00321     //LayoutWindowElements();
00322     //ComputeContentSize();
00323   }
00324 
00325   void BaseWindow::LayoutWindowElements()
00326   {
00327     // Define the geometry of some of the component of the window. Otherwise, if the composition layout is not set,
00328     // then the component won't be correctly placed after a SetGeometry. This can be redondant if the composition layout is set.
00329     Geometry base = GetGeometry();
00330   }
00331 
00332   void BaseWindow::SetBorder(int border)
00333   {
00334     if (m_Border != border)
00335     {
00336       m_Border = border;
00337     }
00338   }
00339 
00340   void BaseWindow::SetTopBorder(int border)
00341   {
00342     if (m_TopBorder != border)
00343     {
00344       m_TopBorder = border;
00345     }
00346   }
00347 
00348   int BaseWindow::GetBorder() const
00349   {
00350     return m_Border;
00351   }
00352 
00353   int BaseWindow::GetTopBorder() const
00354   {
00355     return m_TopBorder;
00356   }
00357 
00358   void BaseWindow::ShowWindow(bool visible, bool StartModal /*  = false */)
00359   {
00360     if (visible == _is_visible)
00361       return;
00362 
00363     _is_visible = visible;
00364     _is_modal = StartModal;
00365 
00366     if (_is_visible)
00367     {
00368       if (m_layout)
00369       {
00370         m_layout->SetGeometry(GetGeometry());
00371       }
00372 
00373       _entering_visible_state = true;
00374 
00375       sigVisible.emit(this);
00376       GetWindowThread()->GetWindowCompositor().sigVisibleViewWindow.emit(this);
00377 
00378       ComputeContentSize();
00379     }
00380     else
00381     {
00382       _entering_hidden_state = true;
00383       sigHidden.emit(this);
00384       GetWindowThread()->GetWindowCompositor().sigHiddenViewWindow.emit(this);
00385     }
00386 
00387     if (_is_modal)
00388       GetWindowThread()->GetWindowCompositor().StartModalWindow(ObjectWeakPtr<BaseWindow>(this));
00389 
00390     // Whether this view is added or removed, call QueueDraw. in the case where this view is removed, this is a signal
00391     // that the region below this view need to be redrawn.
00392     QueueDraw();
00393   }
00394 
00395   bool BaseWindow::IsVisible() const
00396   {
00397     return _is_visible;
00398   }
00399 
00400   void BaseWindow::StopModal()
00401   {
00402     _is_visible = false;
00403     _is_modal = false;
00404     //ShowWindow(false);
00405     GetWindowThread()->GetWindowCompositor().StopModalWindow(ObjectWeakPtr<BaseWindow> (this));
00406   }
00407 
00408   bool BaseWindow::IsModal() const
00409   {
00410     return _is_modal;
00411   }
00412 
00413   void BaseWindow::NotifyConfigurationChange(int Width, int Height)
00414   {
00415     Geometry geo = GetGeometry();
00416 
00417     if (m_configure_notify_callback)
00418     {
00419       (*m_configure_notify_callback) (GetGraphicsDisplay()->GetWindowWidth(), GetGraphicsDisplay()->GetWindowHeight(), geo, m_configure_notify_callback_data);
00420 
00421       if (geo.IsNull())
00422       {
00423         nuxDebugMsg("[BaseWindow::NotifyConfigurationChange] Received an invalid Geometry.");
00424         geo = GetGeometry();
00425       }
00426       else
00427       {
00428         Area::SetGeometry(geo);
00429         // Get the geometry adjusted with respect to min and max dimension of this area.
00430         geo = GetGeometry();
00431       }
00432     }
00433     else
00434     {
00435       return;
00436     }
00437   }
00438 
00439   void BaseWindow::SetBackgroundLayer(AbstractPaintLayer *layer)
00440   {
00441     NUX_RETURN_IF_NULL(layer);
00442     _paint_layer.reset(layer->Clone());
00443   }
00444 
00445   void BaseWindow::SetBackgroundColor(const Color &color)
00446   {
00447     _paint_layer.reset(new ColorLayer(color));
00448   }
00449 
00450   void BaseWindow::PushHigher(BaseWindow* floating_view)
00451   {
00452     GetWindowThread()->GetWindowCompositor().PushHigher(this, floating_view);
00453   }
00454 
00455   void BaseWindow::PushToFront()
00456   {
00457     GetWindowThread()->GetWindowCompositor().PushToFront(this);
00458   }
00459 
00460   void BaseWindow::PushToBack()
00461   {
00462     GetWindowThread()->GetWindowCompositor().PushToBack(this);
00463   }
00464 
00465   bool BaseWindow::ChildNeedsRedraw()
00466   {
00467     return _child_need_redraw;
00468   }
00469 
00470   void* BaseWindow::GetBackupTextureData(int &width, int &height, int &format)
00471   {
00472     return GetWindowThread()->GetWindowCompositor().GetBackupTextureData(this, width, height, format);
00473   }
00474 
00475   void BaseWindow::SetEnterFocusInputArea(InputArea *input_area)
00476   {
00477     if (_enter_focus_input_area)
00478     {
00479       _enter_focus_input_area->UnReference();
00480     }
00481 
00482     _enter_focus_input_area = input_area;
00483     if (_enter_focus_input_area)
00484       _enter_focus_input_area->Reference();
00485 
00486   }
00487 
00488   void BaseWindow::SetOpacity(float opacity)
00489   {
00490     if (_opacity == opacity)
00491       return;
00492 
00493     _opacity = opacity;
00494 
00495     _opacity = CLAMP(_opacity, 0.0f, 1.0f);
00496 
00497     QueueDraw();
00498   }
00499 
00500   float BaseWindow::GetOpacity()
00501   {
00502     return _opacity;
00503   }
00504 
00505   void BaseWindow::SetAcceptKeyNavFocus(bool accept)
00506   {
00507     accept_key_nav_focus_ = accept;
00508   }
00509 
00510   bool BaseWindow::AcceptKeyNavFocus()
00511   {
00512     return accept_key_nav_focus_;
00513   }
00514 }