Back to index

nux  3.0.0
View.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 #include "WindowCompositor.h"
00025 #include "Layout.h"
00026 #include "View.h"
00027 
00028 namespace nux
00029 {
00030 
00031   NUX_IMPLEMENT_OBJECT_TYPE(View);
00032 
00033   View::View(NUX_FILE_LINE_DECL)
00034     :   InputArea(NUX_FILE_LINE_PARAM)
00035   {
00036     view_layout_ = NULL;
00037     draw_cmd_queued_        = false;
00038     m_TextColor         = Color(1.0f, 1.0f, 1.0f, 1.0f);
00039   }
00040 
00041   View::~View()
00042   {
00043     // It is possible that the window thread has been deleted before the view
00044     // itself, so check prior to calling.
00045     WindowThread* wt = GetWindowThread();
00046 
00047     if (wt)
00048     {
00049       // It is possible that the object is in the refresh list. Remove it here
00050       // before it is deleted.
00051       wt->RemoveObjectFromLayoutQueue(this);
00052     }
00053 
00054     RemoveLayout();
00055   }
00056 
00057   long View::ComputeContentSize()
00058   {
00059     if (view_layout_)
00060     {
00061       PreLayoutManagement();
00062 
00063       int PreWidth = GetBaseWidth();
00064       int PreHeight = GetBaseHeight();
00065 
00066       long ret = view_layout_->ComputeContentSize();
00067 
00068       PostLayoutManagement(ret);
00069 
00070       int PostWidth = GetBaseWidth();
00071       int PostHeight = GetBaseHeight();
00072 
00073       long size_compliance = 0;
00074 
00075       // The layout has been resized to tightly pack its content
00076       if (PostWidth > PreWidth)
00077       {
00078         size_compliance |= eLargerWidth; // need scrollbar
00079       }
00080       else if (PostWidth < PreWidth)
00081       {
00082         size_compliance |= eSmallerWidth;
00083       }
00084       else
00085       {
00086         size_compliance |= eCompliantWidth;
00087       }
00088 
00089       // The layout has been resized to tightly pack its content
00090       if (PostHeight > PreHeight)
00091       {
00092         size_compliance |= eLargerHeight; // need scrollbar
00093       }
00094       else if (PostHeight < PreHeight)
00095       {
00096         size_compliance |= eSmallerHeight;
00097       }
00098       else
00099       {
00100         size_compliance |= eCompliantHeight;
00101       }
00102 
00103       return size_compliance;
00104     }
00105     else
00106     {
00107       PreLayoutManagement();
00108       int ret = PostLayoutManagement(eCompliantHeight | eCompliantWidth);
00109       return ret;
00110     }
00111 
00112     return 0;
00113   }
00114 
00115   void View::ComputeContentPosition(float offsetX, float offsetY)
00116   {
00117     if (view_layout_)
00118     {
00119       view_layout_->SetBaseX(GetBaseX());
00120       view_layout_->SetBaseY(GetBaseY());
00121       view_layout_->ComputeContentPosition(offsetX, offsetY);
00122     }
00123   }
00124 
00125   void View::PreLayoutManagement()
00126   {
00127     // Give the managed layout the same size and position as the Control.
00128     if (view_layout_)
00129       view_layout_->SetGeometry(GetGeometry());
00130   }
00131 
00132   long View::PostLayoutManagement(long LayoutResult)
00133   {
00134     // Set the geometry of the control to be the same as the managed layout.
00135     // Only the size is changed. The position of the composition layout hasn't
00136     // been changed by ComputeContentSize.
00137     if (view_layout_)
00138     {
00139       // If The layout is empty, do not change the size of the parent element.
00140       if (!view_layout_->IsEmpty())
00141         Area::SetGeometry(view_layout_->GetGeometry());
00142     }
00143 
00144     return LayoutResult;
00145   }
00146 
00147   void View::PreResizeGeometry()
00148   {
00149 
00150   }
00151 
00152   void View::PostResizeGeometry()
00153   {
00154   }
00155 
00156   void View::ProcessDraw(GraphicsEngine& graphics_engine, bool force_draw)
00157   {
00158     full_view_draw_cmd_ = false;
00159 
00160     graphics_engine.PushModelViewMatrix(Get2DMatrix());
00161 
00162     if (force_draw)
00163     {
00164       GetPainter().PaintBackground(graphics_engine, GetGeometry());
00165       GetPainter().PushPaintLayerStack();
00166 
00167       draw_cmd_queued_ = true;
00168       full_view_draw_cmd_ = true;
00169       Draw(graphics_engine, force_draw);
00170       DrawContent(graphics_engine, force_draw);
00171       PostDraw(graphics_engine, force_draw);
00172 
00173       GetPainter().PopPaintLayerStack();
00174     }
00175     else
00176     {
00177       if (draw_cmd_queued_)
00178       {
00179         GetPainter().PaintBackground(graphics_engine, GetGeometry());
00180         GetPainter().PushPaintLayerStack();
00181 
00182         full_view_draw_cmd_ = true;
00183         Draw(graphics_engine, false);
00184         DrawContent(graphics_engine, false);
00185         PostDraw(graphics_engine, false);
00186 
00187         GetPainter().PopPaintLayerStack();
00188       }
00189       else
00190       {
00191         DrawContent(graphics_engine, false);
00192         PostDraw(graphics_engine, false);
00193       }
00194     }
00195 
00196     graphics_engine.PopModelViewMatrix();
00197 
00198     draw_cmd_queued_ = false;
00199     full_view_draw_cmd_ = false;
00200   }
00201 
00202   void View::Draw(GraphicsEngine &graphics_engine, bool force_draw)
00203   {
00204 
00205   }
00206 
00207   void View::DrawContent(GraphicsEngine &graphics_engine, bool force_draw)
00208   {
00209 
00210   }
00211 
00212   void View::PostDraw(GraphicsEngine &graphics_engine, bool force_draw)
00213   {
00214 
00215   }
00216 
00217   void View::QueueDraw()
00218   {
00219     if (draw_cmd_queued_)
00220       return;
00221 
00222     //GetWindowCompositor()..AddToDrawList(this);
00223     WindowThread* application = GetWindowThread();
00224     if (application)
00225     {
00226       application->AddToDrawList(this);
00227       application->RequestRedraw();
00228       //GetWindowCompositor().AddToDrawList(this);
00229     }
00230     if (view_layout_)
00231       view_layout_->QueueDraw();
00232 
00233     draw_cmd_queued_ = true;
00234     OnQueueDraw.emit(this);
00235   }
00236 
00237   void View::NeedSoftRedraw()
00238   {
00239     //GetWindowCompositor()..AddToDrawList(this);
00240     WindowThread* application = GetWindowThread();
00241     if (application)
00242     {
00243         application->AddToDrawList(this);
00244         application->RequestRedraw();
00245     }
00246     //draw_cmd_queued_ = false;
00247   }
00248 
00249   bool View::IsRedrawNeeded()
00250   {
00251     return draw_cmd_queued_;
00252   }
00253 
00254   bool View::IsFullRedraw() const
00255   {
00256     return full_view_draw_cmd_;
00257   }
00258 
00259   void View::DoneRedraw()
00260   {
00261     draw_cmd_queued_ = false;
00262 
00263     if (view_layout_)
00264     {
00265       view_layout_->DoneRedraw();
00266     }
00267   }
00268 
00269   Layout* View::GetLayout()
00270   {
00271     return view_layout_;
00272   }
00273 
00274   Layout *View::GetCompositionLayout()
00275   {
00276     return GetLayout();
00277   }
00278 
00279   bool View::SetLayout(Layout *layout)
00280   {
00281     NUX_RETURN_VALUE_IF_NULL(layout, false);
00282     nuxAssert(layout->IsLayout());
00283     NUX_RETURN_VALUE_IF_TRUE(view_layout_ == layout, true);
00284 
00285     Area *parent = layout->GetParentObject();
00286 
00287     if (parent == this)
00288     {
00289       nuxAssert(view_layout_ == layout);
00290       return false;
00291     }
00292     else if (parent != 0)
00293     {
00294       nuxDebugMsg(0, "[View::SetCompositionLayout] Object already has a parent. You must UnParent the object before you can parenting again.");
00295       return false;
00296     }
00297 
00298     if (view_layout_)
00299     {
00300       /* we need to emit the signal before the unparent, just in case
00301          one of the callbacks wanted to use this object */
00302 
00303       LayoutRemoved.emit(this, view_layout_);
00304       view_layout_->UnParentObject();
00305     }
00306     layout->SetParentObject(this);
00307     view_layout_ = layout;
00308 
00309     GetWindowThread()->QueueObjectLayout(this);
00310 
00311     LayoutAdded.emit(this, view_layout_);
00312 
00313     return true;
00314   }
00315 
00316   void View::OnChildFocusChanged(/*Area *parent,*/ Area *child)
00317   {
00318     ChildFocusChanged.emit(/*parent,*/ child);
00319   }
00320 
00321   bool View::SetCompositionLayout(Layout *layout)
00322   {
00323     return SetLayout(layout);
00324   }
00325 
00326   void View::RemoveLayout()
00327   {
00328     NUX_RETURN_IF_NULL(view_layout_);
00329 
00330     if (view_layout_)
00331       view_layout_->UnParentObject();
00332 
00333     view_layout_ = 0;
00334   }
00335 
00336   void View::RemoveCompositionLayout()
00337   {
00338     RemoveLayout();
00339   }
00340 
00341   bool View::SearchInAllSubNodes(Area *bo)
00342   {
00343     if (view_layout_)
00344       return view_layout_->SearchInAllSubNodes(bo);
00345 
00346     return false;
00347   }
00348 
00349   bool View::SearchInFirstSubNodes(Area *bo)
00350   {
00351     if (view_layout_)
00352       return view_layout_->SearchInFirstSubNodes(bo);
00353 
00354     return false;
00355   }
00356 
00357   void View::SetGeometry(const Geometry &geo)
00358   {
00359     Area::SetGeometry(geo);
00360     ComputeContentSize();
00361     PostResizeGeometry();
00362   }
00363 
00364   void View::SetFont(ObjectPtr<FontTexture> font)
00365   {
00366     _font = font;
00367   }
00368 
00369   ObjectPtr<FontTexture> View::GetFont()
00370   {
00371     if (!_font.IsValid())
00372       _font = GetSysFont();
00373     return _font;
00374   }
00375 
00376   void View::SetTextColor(const Color &color)
00377   {
00378     m_TextColor = color;
00379   }
00380 
00381   Color View::GetTextColor()
00382   {
00383     return m_TextColor;
00384   }
00385 
00386   void View::EnableView()
00387   {
00388     view_enabled_ = true;
00389   }
00390 
00391   void View::DisableView()
00392   {
00393     view_enabled_ = false;
00394   }
00395 
00396   void View::SetEnableView(bool enable)
00397   {
00398     if (enable)
00399     {
00400       EnableView();
00401     }
00402     else
00403     {
00404       DisableView();
00405     }
00406   }
00407 
00408   bool View::IsViewEnabled() const
00409   {
00410     return view_enabled_;
00411   }
00412 
00413   void View::GeometryChangePending()
00414   {
00415     if (IsLayoutDone())
00416       QueueDraw();
00417   }
00418 
00419   void View::GeometryChanged()
00420   {
00421     if (IsLayoutDone())
00422       QueueDraw();
00423   }
00424 
00425   Area* View::FindAreaUnderMouse(const Point& mouse_position, NuxEventType event_type)
00426   {
00427     bool mouse_inside = TestMousePointerInclusionFilterMouseWheel(mouse_position, event_type);
00428 
00429     if (mouse_inside == false)
00430       return NULL;
00431 
00432     if (view_layout_)
00433     {
00434       Area* view = view_layout_->FindAreaUnderMouse(mouse_position, event_type);
00435 
00436       if (view)
00437         return view;
00438     }
00439 
00440     if ((event_type == NUX_MOUSE_WHEEL) && (!AcceptMouseWheelEvent()))
00441       return NULL;
00442     return this;
00443   }
00444 
00445   Area* View::FindKeyFocusArea(unsigned int key_symbol,
00446                       unsigned long x11_key_code,
00447                       unsigned long special_keys_state)
00448   {
00449     if (has_key_focus_)
00450     {
00451       return this;
00452     }
00453     else if (next_object_to_key_focus_area_)
00454     {
00455       return next_object_to_key_focus_area_->FindKeyFocusArea(key_symbol, x11_key_code, special_keys_state);
00456     }
00457     return NULL;
00458   }
00459 
00460   Area* View::KeyNavIteration(KeyNavDirection direction)
00461   {
00462     if (next_object_to_key_focus_area_)
00463     {
00464       return NULL;
00465     }
00466 
00467     if (IsVisible() == false)
00468       return NULL;
00469 
00470     if (AcceptKeyNavFocus())
00471     {
00472       QueueDraw();
00473       return this;
00474     }
00475     else if (view_layout_)
00476     {
00477       return view_layout_->KeyNavIteration(direction);
00478     }
00479 
00480     return NULL;
00481   }
00482 
00483   bool View::AcceptKeyNavFocus()
00484   {
00485     return true;
00486   }
00487 }