Back to index

nux  3.0.0
FloatingWindow.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 
00023 #include "Nux.h"
00024 
00025 #include "NuxGraphics/GLTextureResourceManager.h"
00026 
00027 #include "HLayout.h"
00028 #include "WindowThread.h"
00029 #include "WindowCompositor.h"
00030 #include "FloatingWindow.h"
00031 
00032 namespace nux
00033 {
00034   NUX_IMPLEMENT_OBJECT_TYPE(FloatingWindow);
00035 
00036   /*
00037       Elements inside the Window have coordinates based on the top-left corner of the window.
00038       This is true whether we are drawing or computing the layout. When computing the layout, use x_root and y_root to
00039       pass the top-left corner position of the window. When drawing, make a similar adjustment.
00040   */
00041   FloatingWindow::FloatingWindow(const char *WindowName, NUX_FILE_LINE_DECL)
00042     :   BaseWindow(WindowName, NUX_FILE_LINE_PARAM)
00043   {
00044     m_bIsVisible                = false;
00045     m_bSizeMatchLayout          = false;
00046     m_bIsModal                  = false;
00047     m_bIsVisibleSizeGrip        = true;
00048     m_SizeGripDragPositionX     = 0;
00049     m_SizeGripDragPositionY     = 0;
00050     m_hasTitleBar               = true;
00051     _resize_handle_width        = 20;
00052     _resize_handle_height       = 20;
00053     _title_bar_height           = 20;
00054 
00055     _minimize_button    = new InputArea(NUX_TRACKER_LOCATION);
00056     _minimize_button->SetParentObject(this);
00057 
00058     _resize_handle      = new InputArea(NUX_TRACKER_LOCATION);
00059     _resize_handle->SinkReference();
00060     _resize_handle->SetParentObject(this);
00061 
00062     _title_bar          = new InputArea(NUX_TRACKER_LOCATION);
00063     _title_bar->SinkReference();
00064     _title_bar->SetParentObject(this);
00065 
00066     _close_button       = new InputArea(NUX_TRACKER_LOCATION);
00067     _window_title_bar   = new StaticTextBox("", NUX_TRACKER_LOCATION);
00068 
00069     _title_bar_layout   = new HLayout(NUX_TRACKER_LOCATION);
00070     _title_bar_layout->Reference();
00071     
00072     _minimize_button->SetMinMaxSize(20, 20);
00073     _minimize_button->SetGeometry(0, 0, 20, 20);
00074     _close_button->SetMinimumSize(20, 20);
00075     _close_button->SetGeometry(0, 0, 20, 20);
00076     _resize_handle->SetMinimumSize(_resize_handle_width, _resize_handle_height);
00077     _resize_handle->SetGeometry(Geometry(0, 0, _resize_handle_width, _resize_handle_height));
00078 
00079     _title_bar->mouse_down.connect(sigc::mem_fun(this, &FloatingWindow::RecvTitleBarMouseDown));
00080     _title_bar->mouse_drag.connect(sigc::mem_fun(this, &FloatingWindow::RecvTitleBarMouseDrag));
00081     _close_button->mouse_click.connect(sigc::mem_fun(this, &FloatingWindow::RecvCloseButtonClick));
00082 
00083     _resize_handle->mouse_drag.connect(sigc::mem_fun(this, &FloatingWindow::OnSizeGrigMouseDrag));
00084     _resize_handle->mouse_down.connect(sigc::mem_fun(this, &FloatingWindow::OnSizeGrigMouseDown));
00085 
00086     _title_bar_layout->AddView((_window_title_bar), 1, eCenter, eFix);
00087     _title_bar_layout->AddView((_close_button), 0, eCenter, eFix);
00088     _title_bar_layout->SetParentObject(this);
00089 
00090 
00091     if (HasTitleBar())
00092       SetTopBorder(24);
00093     else
00094       SetTopBorder(6);
00095 
00096     SetBorder(2);
00097 
00098     SetMinimumSize(32, 32);
00099     SetGeometry(Geometry(100, 100, 320, 200));
00100 
00101     NString Path = NUX_FINDRESOURCELOCATION("UITextures/AddButton.png");
00102     MinimizeIcon = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture();
00103     MinimizeIcon->Update(Path.GetTCharPtr());
00104     Path = NUX_FINDRESOURCELOCATION("UITextures/CancelButton.png");
00105     CloseIcon = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture();
00106     CloseIcon->Update(Path.GetTCharPtr());
00107 
00108     SetWindowTitle(WindowName);
00109   }
00110 
00111   FloatingWindow::~FloatingWindow()
00112   {
00113     m_InterfaceObject.clear();
00114 
00115     _resize_handle->UnParentObject();
00116     _resize_handle->UnReference();
00117 
00118     _title_bar->UnParentObject();
00119     _title_bar->UnReference();
00120 
00121     _minimize_button->UnReference();
00122     CloseIcon->UnReference();
00123     MinimizeIcon->UnReference();
00124     
00125     _title_bar_layout->UnParentObject();
00126     _title_bar_layout->UnReference();
00127   }
00128 
00129   Area* FloatingWindow::FindAreaUnderMouse(const Point& mouse_position, NuxEventType event_type)
00130   {
00131     bool mouse_inside = TestMousePointerInclusionFilterMouseWheel(mouse_position, event_type);
00132 
00133     if (mouse_inside == false)
00134       return NULL;
00135 
00136     NUX_RETURN_VALUE_IF_TRUE(_resize_handle->TestMousePointerInclusion(mouse_position, event_type), _resize_handle);
00137     NUX_RETURN_VALUE_IF_TRUE(_close_button->TestMousePointerInclusion(mouse_position, event_type), _close_button);
00138 
00139     if (HasTitleBar())
00140     {
00141       NUX_RETURN_VALUE_IF_TRUE(_title_bar->TestMousePointerInclusion(mouse_position, event_type), _title_bar);
00142     }
00143 
00144 //     if (_title_bar_layout)
00145 //     {
00146 //       nuxAssert(_title_bar_layout->IsLayout());
00147 //       Area* found_area = _title_bar_layout->FindAreaUnderMouse(mouse_position, event_type);
00148 //       if (found_area)
00149 //         return found_area;
00150 //     }
00151 
00152     if (m_layout)
00153     {
00154       nuxAssert(m_layout->IsLayout());
00155       Area* found_area = m_layout->FindAreaUnderMouse(mouse_position, event_type);
00156       if (found_area)
00157         return found_area;
00158     }
00159 
00160     if ((event_type == NUX_MOUSE_WHEEL) && (!AcceptMouseWheelEvent()))
00161       return NULL;
00162     return this;
00163   }
00164 
00165   void FloatingWindow::Draw(GraphicsEngine &graphics_engine, bool force_draw)
00166   {
00167     Geometry base = GetGeometry();
00168     // The elements position inside the window are referenced to top-left window corner. So bring base to(0, 0).
00169     base.SetX(0);
00170     base.SetY(0);
00171     graphics_engine.PushClippingRectangle(base);
00172 
00173     GetPainter().PushDrawShapeLayer(graphics_engine, base, eSHAPE_CORNER_ROUND10, Color(0xFF707070), eCornerTopLeft | eCornerTopRight, true);
00174 
00175     if (HasTitleBar())
00176     {
00177       GetPainter().PaintShapeCorner(graphics_engine, Geometry(_title_bar->GetBaseX(), _title_bar->GetBaseY(),
00178                                  _title_bar->GetBaseWidth(), _title_bar->GetBaseHeight()), Color(0xFF2f2f2f),
00179                                  eSHAPE_CORNER_ROUND10, eCornerTopLeft | eCornerTopRight);
00180 
00181       GetPainter().PaintTextLineStatic(graphics_engine, GetSysBoldFont(), _window_title_bar->GetGeometry(), _window_title, Color(0xFFFFFFFF), true, eAlignTextCenter);
00182       GetPainter().Draw2DTextureAligned(graphics_engine, CloseIcon, _close_button->GetGeometry(), TextureAlignmentStyle(eTACenter, eTACenter));
00183     }
00184 
00185     GetPainter().PopBackground();
00186     graphics_engine.PopClippingRectangle();
00187   }
00188 
00189   void FloatingWindow::DrawContent(GraphicsEngine &graphics_engine, bool force_draw)
00190   {
00191     Geometry base = GetGeometry();
00192     // The elements position inside the window are referenced to top-left window corner. So bring base to(0, 0).
00193     base.SetX(0);
00194     base.SetY(0);
00195 
00196     GetPainter().PushShapeLayer(graphics_engine, base, eSHAPE_CORNER_ROUND10, Color(0xFF707070), eCornerTopLeft | eCornerTopRight, true);
00197 
00198     if (m_layout)
00199     {
00200       graphics_engine.PushClippingRectangle(base);
00201 
00202       m_layout->ProcessDraw(graphics_engine, force_draw);
00203 
00204       graphics_engine.PopClippingRectangle();
00205     }
00206 
00207     GetPainter().PopBackground();
00208   }
00209 
00210   void FloatingWindow::PostDraw(GraphicsEngine &graphics_engine, bool force_draw)
00211   {
00212     if (force_draw == false)
00213     {
00214       return;
00215     }
00216 
00217     if ((IsVisibleSizeGrip() == true) && (IsSizeMatchContent() == false))
00218     {
00219       // Do not draw the size grip if the window is constrained by the size of the container layout.
00220       Geometry geo = _resize_handle->GetGeometry();
00221       graphics_engine.QRP_Triangle(geo.x + geo.width, geo.y, geo.x, geo.y + geo.height, geo.x + geo.width, geo.y + geo.height, Color(0xFF999999));
00222     }
00223   }
00224 
00225   void FloatingWindow::EnableTitleBar(bool b)
00226   {
00227     m_hasTitleBar = b;
00228     ComputeContentSize();
00229   }
00230 
00231   bool FloatingWindow::HasTitleBar() const
00232   {
00233     return m_hasTitleBar;
00234   }
00235 
00236   void FloatingWindow::OnSizeGrigMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
00237   {
00238     if (IsSizeMatchContent())
00239     {
00240       return;
00241     }
00242 
00243     // Do not let the _resize_handle test the event because the window is not displaying it;
00244     int XGrip = x;
00245     int YGrip = y;
00246 
00247 
00248     // We want to false on one half of the size grip square to register a mouse down. This is meant to leave more room
00249     // for the scrollbar buttons(if any) at the bottom right of the window.
00250     if ((XGrip > 0) && (YGrip > 0) && (XGrip > _resize_handle_height - YGrip))
00251     {
00252        // has grip
00253     }
00254 
00255     m_SizeGripDragPositionX = x;
00256     m_SizeGripDragPositionY = y;
00257     //GetWindowCompositor().SetMouseFocusArea(this);
00258   }
00259 
00260   void FloatingWindow::OnSizeGrigMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
00261   {
00262     if (IsSizeMatchContent())
00263     {
00264       return;
00265     }
00266 
00267     Geometry geo;
00268     geo = GetGeometry();
00269 
00270     int ddx = 0;
00271     int ddy = 0;
00272 
00273     if ((dx > 0) && (x > m_SizeGripDragPositionX))
00274     {
00275       ddx = dx;
00276     }
00277 
00278     if ((dx < 0) && (x < m_SizeGripDragPositionX))
00279     {
00280       ddx = dx;
00281     }
00282 
00283     if ((dy > 0) && (y > m_SizeGripDragPositionY))
00284     {
00285       ddy = dy;
00286     }
00287 
00288     if ((dy < 0) && (y < m_SizeGripDragPositionY))
00289     {
00290       ddy = dy;
00291     }
00292 
00293     geo.OffsetSize(ddx, ddy);
00294 
00295     SetGeometry(geo);
00296 
00297 #if defined(NUX_OS_LINUX)
00298     if (m_input_window != 0)
00299     {
00300       //nuxDebugMsg("Resize Input window: %d, %d, %d, %d", geo.x, geo.y, geo.width, geo.height);
00301       m_input_window->SetGeometry(GetGeometry());
00302     }
00303 #endif
00304 
00305     GetWindowThread()->QueueObjectLayout(this);
00306     QueueDraw();
00307   }
00308 
00309   void FloatingWindow::RecvTitleBarMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
00310   {
00311     _title_bar_mouse_down_location = Point(x, y);
00312   }
00313 
00314   void FloatingWindow::RecvTitleBarMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
00315   {
00316     Geometry geo;
00317     geo = GetGeometry();
00318     geo.OffsetPosition(dx, dy);
00319 
00320     // Set the Window Size and Position
00321     Area::SetGeometry(geo);
00322     // No need to compute the window layout elements [LayoutWindowElements()]. They haven't changed.
00323     // No need to compute the layout [ComputeContentSize()]. It hasn't changed.
00324 
00325     _title_bar->SetGeometry(0, 0, geo.GetWidth(), _title_bar_height);
00326 
00327 #if defined(NUX_OS_LINUX)
00328     if (m_input_window != 0)
00329     {
00330       //nuxDebugMsg("Resize Input window: %d, %d, %d, %d", geo.x, geo.y, geo.width, geo.height);
00331       m_input_window->SetGeometry(GetGeometry());
00332     }
00333 #endif
00334 
00335     QueueDraw();
00336   }
00337 
00338   void FloatingWindow::RecvCloseButtonClick(int x, int y, unsigned long button_flags, unsigned long key_flags)
00339   {
00340 #if defined(NUX_OS_LINUX)
00341     // Disable the input window if there is one.
00342     EnableInputWindow(false);
00343 #endif
00344     
00345     StopModal();
00346   }
00347 
00348 // Get a change to do any work on an element.
00349 // Here we need to position the header by hand because it is not under the control of vlayout.
00350   void FloatingWindow::PreLayoutManagement()
00351   {
00352     Geometry geo = GetGeometry();
00353 
00354     if (m_configure_notify_callback)
00355     {
00356       (*m_configure_notify_callback) (GetGraphicsDisplay()->GetWindowWidth(), GetGraphicsDisplay()->GetWindowHeight(), geo, m_configure_notify_callback_data);
00357 
00358       if (geo.IsNull())
00359       {
00360         nuxDebugMsg("[FloatingWindow::PreLayoutManagement] Received an invalid Geometry.");
00361         geo = GetGeometry();
00362       }
00363       else
00364       {
00365         Area::SetGeometry(geo);
00366         // Get the geometry adjusted with respect to min and max dimension of this area.
00367         geo = GetGeometry();
00368       }
00369     }
00370 
00371     // Drag Bar Geometry
00372     if (HasTitleBar())
00373     {
00374       _title_bar->SetGeometry(0, 0, geo.GetWidth(), _title_bar_height);
00375     }
00376 
00377     // Size grip Geometry
00378     Geometry SizeGripGeometry(geo.GetWidth() - _resize_handle_width, geo.GetHeight() - _resize_handle_height,
00379                                _resize_handle_width, _resize_handle_height);
00380     _resize_handle->SetGeometry(SizeGripGeometry);
00381 
00382     if (m_layout)
00383     {
00384       Geometry layout_geo = Geometry(m_Border, m_TopBorder,
00385                                       geo.GetWidth() - 2 * m_Border, geo.GetHeight() - m_Border - m_TopBorder);
00386       m_layout->SetGeometry(layout_geo);
00387     }
00388   }
00389 
00390 // Get a change to do any work on an element.
00391 // Here we need to position the header by hand because it is not under the control of vlayout.
00392   long FloatingWindow::PostLayoutManagement(long LayoutResult)
00393   {
00394     if (IsSizeMatchContent() && m_layout)
00395     {
00396       Geometry layout_geometry = m_layout->GetGeometry();
00397 
00398       Geometry WindowGeometry = Geometry(GetGeometry().x,
00399                                           GetGeometry().y,
00400                                           layout_geometry.GetWidth() + 2 * m_Border,
00401                                           layout_geometry.GetHeight() + m_Border + m_TopBorder);
00402 
00403       Area::SetGeometry(WindowGeometry);
00404     }
00405 
00406     Geometry geo = GetGeometry();
00407 
00408     // Drag Bar Geometry
00409     if (HasTitleBar())
00410     {
00411       _title_bar->SetGeometry(0, 0, geo.GetWidth(), _title_bar_height);
00412     }
00413 
00414     // Size grip Geometry
00415     Geometry temp(geo.GetWidth() - _resize_handle_width, geo.GetHeight() - _resize_handle_height,
00416                    _resize_handle_width, _resize_handle_height);
00417     _resize_handle->SetGeometry(temp);
00418 
00419     // Title Bar
00420     _title_bar_layout->SetGeometry(_title_bar->GetGeometry());
00421     GetWindowThread()->ComputeElementLayout(_title_bar_layout);
00422 
00423     // A FloatingWindow must kill the result of the management and pass it to the parent Layout.
00424     return (eCompliantHeight | eCompliantWidth);
00425     //return result;
00426   }
00427 
00428 // Get a change to do any work on an element.
00429 // Here we need to position the header by hand because it is not under the control of vlayout.
00430   void FloatingWindow::ComputeContentPosition(float offsetX, float offsetY)
00431   {
00432     //ScrollView::ComputeContentPosition(offsetX, offsetY);
00433 
00434     Geometry geo = GetGeometry();
00435 
00436     // Drag Bar Geometry
00437     if (HasTitleBar())
00438     {
00439       _title_bar->SetGeometry(0, 0, geo.GetWidth(), _title_bar_height);
00440     }
00441 
00442     // Size grip Geometry
00443     Geometry temp(geo.GetWidth() - _resize_handle_width, geo.GetHeight() - _resize_handle_height,
00444                    _resize_handle_width, _resize_handle_height);
00445     _resize_handle->SetGeometry(temp);
00446 
00447     // Title Bar
00448     _title_bar_layout->SetGeometry(_title_bar->GetGeometry());
00449     GetWindowThread()->ComputeElementLayout(_title_bar_layout);
00450 
00451   }
00452 
00453   void FloatingWindow::LayoutWindowElements()
00454   {
00455     // Define the geometry of some of the component of the window. Otherwise, if the composition layout is not set,
00456     // then the component won't be correctly placed after a SetGeometry. This can be redundant if the composition layout is set.
00457     Geometry base = GetGeometry();
00458     _title_bar->SetGeometry(0, 0, base.GetWidth(), _title_bar_height);
00459 
00460     _title_bar_layout->SetGeometry(_title_bar->GetGeometry());
00461     GetWindowThread()->ComputeElementLayout(_title_bar_layout);
00462 
00463     // Size grip Geometry
00464     Geometry temp(base.GetWidth() - _resize_handle_width, base.GetHeight() - _resize_handle_height,
00465                    _resize_handle_width, _resize_handle_height);
00466     _resize_handle->SetGeometry(temp);
00467   }
00468 
00469   void FloatingWindow::SetWindowTitle(const char *title)
00470   {
00471     NUX_RETURN_IF_NULL(title)
00472     _window_title = title;
00473   }
00474 
00475   NString FloatingWindow::GetWindowTitle()
00476   {
00477     return _window_title;
00478   }
00479 
00480 }