nux-1.16.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 "NuxGraphics/GLSh_DrawFunction.h" 00026 #include "NuxGraphics/GpuDevice.h" 00027 #include "NuxGraphics/GLDeviceObjects.h" 00028 00029 #include "TimeGraph.h" 00030 00031 #include "VLayout.h" 00032 #include "HLayout.h" 00033 #include "Button.h" 00034 #include "StaticTextBox.h" 00035 00036 namespace nux 00037 { 00038 NUX_IMPLEMENT_OBJECT_TYPE (TimeGraph); 00039 00040 TimeGraph::Graph::Graph (Color PrimaryColor, Color SecondaryColor) 00041 : m_HasBeenUpdated (false) 00042 { 00043 m_PrimaryColor = PrimaryColor; 00044 m_SecondaryColor = SecondaryColor; 00045 } 00046 00047 TimeGraph::Graph::Graph (const Graph &graph) 00048 { 00049 m_PrimaryColor = graph.m_PrimaryColor; 00050 m_SecondaryColor = graph.m_SecondaryColor; 00051 m_HasBeenUpdated = graph.m_HasBeenUpdated; 00052 m_ValueList = graph.m_ValueList; 00053 } 00054 00055 TimeGraph::Graph &TimeGraph::Graph::operator = (const TimeGraph::Graph &graph) 00056 { 00057 if (this == &graph) 00058 return *this; 00059 00060 m_PrimaryColor = graph.m_PrimaryColor; 00061 m_SecondaryColor = graph.m_SecondaryColor; 00062 m_HasBeenUpdated = graph.m_HasBeenUpdated; 00063 m_ValueList = graph.m_ValueList; 00064 00065 return *this; 00066 } 00067 00068 TimeGraph::Graph::~Graph() 00069 { 00070 Clear(); 00071 } 00072 00073 void TimeGraph::Graph::Update (float Value) 00074 { 00075 m_ValueList.push_front (Value); 00076 00077 if (m_ValueList.size() >= sBufferSize) 00078 { 00079 m_ValueList.pop_back(); 00080 } 00081 00082 m_HasBeenUpdated = false; 00083 } 00084 00085 void TimeGraph::Graph::Clear() 00086 { 00087 m_ValueList.clear(); 00088 m_HasBeenUpdated = false; 00089 } 00090 00091 void TimeGraph::Graph::Reset() 00092 { 00093 00094 } 00095 00096 t_u32 TimeGraph::sBufferSize = 2048; 00097 00098 TimeGraph::TimeGraph (const TCHAR *Title, NUX_FILE_LINE_DECL) 00099 : View (NUX_FILE_LINE_PARAM) 00100 { 00101 m_minY = 0.0f; 00102 m_maxY = 1.0f; 00103 00104 m_Option = SHOW_GRAPH; 00105 m_Title = Title; 00106 00107 InitializeLayout (); 00108 InitializeWidgets (); 00109 } 00110 00111 TimeGraph::~TimeGraph() 00112 { 00113 NUX_SAFE_DELETE (m_DrawFunctionShader); 00114 NUX_SAFE_DELETE (m_BackgroundLayer); 00115 } 00116 00117 void TimeGraph::InitializeWidgets() 00118 { 00119 SetMinimumSize (200, 100); 00120 SetBaseSize (200, 100); 00121 00122 if (!m_Title.IsEmpty() ) 00123 m_GraphTitle->SetText (m_Title); 00124 00125 Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (256, 4, 0, BITFMT_R8G8B8A8); 00126 m_DrawFunctionShader = new GLSh_DrawFunction(); 00127 00128 NTextureData image; 00129 MakeCheckBoardImage (image.GetSurface (0), 64, 64, Color (0xff323232), Color (0xff535353), 8, 8); 00130 BaseTexture* CheckboardPattern = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture (); 00131 CheckboardPattern->Update (&image); 00132 00133 TexCoordXForm texxform; 00134 texxform.SetTexCoordType (TexCoordXForm::OFFSET_COORD); 00135 texxform.SetWrap (TEXWRAP_REPEAT, TEXWRAP_REPEAT); 00136 m_BackgroundLayer = new TextureLayer (CheckboardPattern->GetDeviceTexture(), texxform, color::White); 00137 00138 CheckboardPattern->UnReference (); 00139 00140 m_ValueIcon->SetMinMaxSize (40, 16); 00141 m_GraphIcon->SetMinMaxSize (16, 16); 00142 m_GraphBarIcon->SetMinMaxSize (16, 16); 00143 00144 00145 m_GraphBarIcon->mouse_click.connect (sigc::mem_fun (this, &TimeGraph::RecvShowBarGraphics) ); 00146 m_GraphIcon->mouse_click.connect (sigc::mem_fun (this, &TimeGraph::RecvShowCurveGraphics) ); 00147 m_ValueIcon->mouse_click.connect (sigc::mem_fun (this, &TimeGraph::RecvShowValue) ); 00148 00149 m_GraphTitle->SetFont (GetSysBoldFont() ); 00150 m_hlayout->AddView (new SpaceLayout (40, 40, 0, AREA_MAX_HEIGHT), 1); 00151 m_hlayout->AddView (m_GraphTitle, 1); 00152 m_hlayout->AddView (m_ValueIcon, 0); 00153 m_hlayout->AddView (m_GraphBarIcon, 0); 00154 m_hlayout->AddView (m_GraphIcon, 0); 00155 m_hlayout->SetHorizontalInternalMargin (4); 00156 00157 m_hlayout2->AddLayout (new SpaceLayout (40, 40, 0, AREA_MAX_HEIGHT), 1); 00158 m_hlayout2->AddView (m_GraphArea, 1); 00159 m_hlayout2->AddLayout (new SpaceLayout (50, 40, 0, AREA_MAX_HEIGHT), 1); 00160 00161 m_vlayout->AddLayout (m_hlayout, 0); 00162 m_vlayout->AddLayout (m_hlayout2, 1); 00163 m_vlayout->SetVerticalInternalMargin (2); 00164 00165 SetCompositionLayout (m_vlayout); 00166 SetMinimumSize (200, 120); 00167 } 00168 00169 void TimeGraph::InitializeLayout() 00170 { 00171 m_vlayout = new VLayout (NUX_TRACKER_LOCATION); 00172 m_hlayout = new HLayout (NUX_TRACKER_LOCATION); 00173 m_hlayout2 = new HLayout (TEXT ("QWERTY"), NUX_TRACKER_LOCATION); 00174 m_GraphTitle = new StaticTextBox (TEXT ("Time Graph"), NUX_TRACKER_LOCATION); 00175 m_GraphArea = new InputArea (NUX_TRACKER_LOCATION); 00176 m_GraphBarIcon = new InputArea (NUX_TRACKER_LOCATION); 00177 m_GraphIcon = new InputArea (NUX_TRACKER_LOCATION); 00178 m_ValueIcon = new InputArea (NUX_TRACKER_LOCATION); 00179 } 00180 00181 void TimeGraph::RecvShowBarGraphics (int x, int y, unsigned long button_flags, unsigned long key_flags) 00182 { 00183 m_Option = SHOW_COLUMN; 00184 QueueDraw(); 00185 } 00186 00187 void TimeGraph::RecvShowCurveGraphics (int x, int y, unsigned long button_flags, unsigned long key_flags) 00188 { 00189 m_Option = SHOW_GRAPH; 00190 QueueDraw(); 00191 } 00192 00193 void TimeGraph::RecvShowValue (int x, int y, unsigned long button_flags, unsigned long key_flags) 00194 { 00195 m_Option = SHOW_VALUE; 00196 QueueDraw(); 00197 } 00198 00199 00200 long TimeGraph::ProcessEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo) 00201 { 00202 long ret = m_GraphBarIcon->OnEvent (ievent, TraverseInfo, ProcessEventInfo); 00203 ret = m_GraphIcon->OnEvent (ievent, ret, ProcessEventInfo); 00204 ret = m_ValueIcon->OnEvent (ievent, ret, ProcessEventInfo); 00205 return ret; 00206 } 00207 00208 void TimeGraph::Draw (GraphicsEngine &GfxContext, bool force_draw) 00209 { 00210 Geometry base = GetGeometry(); 00211 00212 GfxContext.PushClippingRectangle (base); 00213 GetPainter().PaintBackground (GfxContext, base); 00214 00215 base.OffsetPosition (1, 1); 00216 base.OffsetSize (-2, -2); 00217 00218 00219 int W = m_GraphArea->GetBaseWidth() - 2; 00220 int H = m_GraphArea->GetBaseHeight() - 2; 00221 int X = m_GraphArea->GetBaseX() + 1; 00222 int Y = m_GraphArea->GetBaseY() + 1; 00223 00224 00225 00226 m_GraphTitle->ProcessDraw (GfxContext, true); 00227 00228 // Draw Graph Background 00229 { 00230 m_BackgroundLayer->SetGeometry (Geometry (X, Y, W, H) ); 00231 m_BackgroundLayer->Renderlayer (GfxContext); 00232 } 00233 00234 { 00235 GetPainter().PaintBackground (GfxContext, m_GraphBarIcon->GetGeometry() ); 00236 GeometryPositioning gp (eHACenter, eVACenter); 00237 Geometry GeoPo = ComputeGeometryPositioning (m_GraphBarIcon->GetGeometry(), GetTheme().GetImageGeometry (eGraphBarIcon), gp); 00238 GetPainter().Paint2DQuadColor (GfxContext, m_GraphBarIcon->GetGeometry(), Color (0xFF000000) ); 00239 GetPainter().PaintShape (GfxContext, GeoPo, Color (0xFFFF9C00), eGraphBarIcon); 00240 } 00241 00242 { 00243 GetPainter().PaintBackground (GfxContext, m_GraphIcon->GetGeometry() ); 00244 GeometryPositioning gp (eHACenter, eVACenter); 00245 Geometry GeoPo = ComputeGeometryPositioning (m_GraphIcon->GetGeometry(), GetTheme().GetImageGeometry (eGraphIcon), gp); 00246 GetPainter().Paint2DQuadColor (GfxContext, m_GraphIcon->GetGeometry(), Color (0xFF000000) ); 00247 GetPainter().PaintShape (GfxContext, GeoPo, Color (0xFFFF9C00), eGraphIcon); 00248 } 00249 00250 { 00251 NString ValueString; 00252 ValueString = NString::Printf (TEXT ("%.2f"), m_maxY); 00253 GetPainter().PaintTextLineStatic (GfxContext, GetSysFont(), Geometry (base.x, Y, 40, 12), ValueString, Color (0xFFFFFFFF) ); 00254 00255 ValueString = NString::Printf (TEXT ("%.2f"), m_minY); 00256 GetPainter().PaintTextLineStatic (GfxContext, GetSysFont(), Geometry (base.x, Y + H - 12, 40, 12), ValueString, Color (0xFFFFFFFF) ); 00257 00258 } 00259 00260 t_u32 numGraph = (t_u32) m_DynValueArray.size(); 00261 t_u32 PosY = Y; 00262 00263 for (t_u32 index = 0; index < numGraph; index++) 00264 { 00265 GeometryPositioning gp (eHACenter, eVACenter); 00266 Geometry GeoPo = ComputeGeometryPositioning (Geometry (X + W + 2, PosY, 8, 12), GetTheme().GetImageGeometry (eDOT6x6), gp); 00267 //GetPainter().Paint2DQuadColor(GfxContext, Geometry(X + W + 2, PosY, 8, 8), 0xFF000000); 00268 GetPainter().PaintShape (GfxContext, GeoPo, m_DynValueArray[index].m_PrimaryColor, eDOT6x6); 00269 00270 NString ValueString; 00271 00272 if (m_DynValueArray[index].m_ValueList.size() == 0) 00273 ValueString = NString::Printf (TEXT ("%.2f"), TEXT ("0.00") ); 00274 else 00275 ValueString = NString::Printf (TEXT ("%.2f"), (*m_DynValueArray[index].m_ValueList.begin() ) ); 00276 00277 GetPainter().PaintTextLineStatic (GfxContext, GetSysFont(), Geometry (X + W + 2 + 6, PosY, 40, 12), ValueString, Color (0xFFFFFFFF), true, eAlignTextCenter); 00278 00279 PosY += 14; 00280 } 00281 00282 if ((m_Option == SHOW_GRAPH) && m_DynValueArray.size()) 00283 { 00284 GfxContext.PushClippingRectangle (m_GraphArea->GetGeometry() ); 00285 t_s32 numGraph = (t_s32) m_DynValueArray.size(); 00286 00287 for (t_s32 index = 0; index < numGraph; index++) 00288 { 00289 if (m_DynValueArray[index].m_ValueList.size() <= 1) 00290 continue; 00291 00292 std::list<float>::iterator it = m_DynValueArray[index].m_ValueList.begin(); 00293 00294 if (Texture->GetWidth() != W) 00295 { 00296 Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (W, 4, 1, BITFMT_R8G8B8A8); 00297 } 00298 00299 it = m_DynValueArray[index].m_ValueList.begin(); 00300 SURFACE_LOCKED_RECT lockrect; 00301 Texture->LockRect (0, &lockrect, 0); 00302 BYTE *dest = (BYTE *) lockrect.pBits; 00303 00304 for (t_s32 i = 0; i < Texture->GetWidth(); i++) 00305 { 00306 float y; 00307 00308 if (it == m_DynValueArray[index].m_ValueList.end() ) 00309 y = 0.0f; 00310 else 00311 { 00312 y = (*it); 00313 it++; 00314 } 00315 00316 y = (y - m_minY) / (m_maxY - m_minY); 00317 00318 for (t_s32 j = 0; j < Texture->GetHeight(); j++) 00319 { 00320 dest[j * lockrect.Pitch + 4* (W - 1 - i) + 0] = 255 * Clamp<float> (y, 0.0f, 1.0f); 00321 dest[j * lockrect.Pitch + 4* (W - 1 - i) + 1] = 255 * Clamp<float> (y, 0.0f, 1.0f); 00322 dest[j * lockrect.Pitch + 4* (W - 1 - i) + 2] = 255 * Clamp<float> (y, 0.0f, 1.0f); 00323 dest[j * lockrect.Pitch + 4* (W - 1 - i) + 3] = 255 * Clamp<float> (y, 0.0f, 1.0f); 00324 } 00325 } 00326 00327 Texture->UnlockRect (0); 00328 GfxContext.GetRenderStates().SetBlend (TRUE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00329 00330 m_DrawFunctionShader->SetTextureFunction (Texture); 00331 m_DrawFunctionShader->SetBackgroundColor (m_DynValueArray[index].m_SecondaryColor); 00332 m_DrawFunctionShader->Render (X, Y, 0, W, H, GfxContext.GetWindowWidth(), GfxContext.GetWindowHeight() ); 00333 00334 GfxContext.GetRenderStates().EnableLineSmooth (TRUE, 1, GL_FASTEST); //You need this blending formula to get anti-aliased lines 00335 00336 it = m_DynValueArray[index].m_ValueList.begin(); 00337 float x0, y0; 00338 x0 = X + W; 00339 y0 = (*it++); 00340 00341 for ( ; it != m_DynValueArray[index].m_ValueList.end(); it++) 00342 { 00343 float x1, y1; 00344 x1 = x0 - 1; 00345 y1 = (*it); 00346 00347 int X0, Y0, X1, Y1; 00348 X0 = x0; //X + W * (x0 - m_minX) / (m_maxX - m_minX); 00349 Y0 = Y + H * ( 1 - (y0 - m_minY) / (m_maxY - m_minY) ); 00350 X1 = x1; //X + W * (x1 - m_minX) / (m_maxX - m_minX); 00351 Y1 = Y + H * ( 1 - (y1 - m_minY) / (m_maxY - m_minY) ); 00352 // NUXTODO: use a vertex buffer instead of sending individual lines 00353 GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (m_DynValueArray[index].m_PrimaryColor) ); 00354 00355 x0 = x1; 00356 y0 = y1; 00357 } 00358 00359 GfxContext.GetRenderStates().EnableLineSmooth (FALSE); 00360 GfxContext.GetRenderStates().SetBlend (GL_FALSE); 00361 } 00362 00363 GfxContext.PopClippingRectangle(); 00364 } 00365 00366 if ((m_Option == SHOW_COLUMN) && m_DynValueArray.size ()) 00367 { 00368 t_u32 BarWidth = W / (t_u32) m_DynValueArray.size(); 00369 00370 if (BarWidth < 10) 00371 BarWidth = 10; 00372 00373 GfxContext.PushClippingRectangle (m_GraphArea->GetGeometry() ); 00374 t_u32 numGraph = (t_u32) m_DynValueArray.size(); 00375 00376 for (t_u32 index = 0; index < numGraph; index++) 00377 { 00378 float x0 = 0.0f; 00379 float y0 = 0.0f; 00380 int X0, Y0; 00381 00382 //y0 = 0.0f; 00383 if (m_DynValueArray[index].m_ValueList.size() != 0) 00384 { 00385 y0 = (*m_DynValueArray[index].m_ValueList.begin() ); 00386 } 00387 00388 x0 = X + W - (index + 1) * BarWidth; 00389 00390 X0 = x0; 00391 Y0 = Y + H * ( 1 - (y0 - m_minY) / (m_maxY - m_minY) ); 00392 00393 if (index == numGraph - 1) 00394 { 00395 if (X0 > X) 00396 { 00397 X0 = X; 00398 BarWidth += W - numGraph * BarWidth; 00399 } 00400 } 00401 00402 GetPainter().Paint2DQuadColor (GfxContext, X0, Y0, BarWidth, Y + H - Y0, m_DynValueArray[index].m_PrimaryColor); 00403 } 00404 00405 GfxContext.PopClippingRectangle(); 00406 } 00407 00408 GetPainter().Paint2DQuadWireframe (GfxContext, m_GraphArea->GetGeometry(), Color (COLOR_BACKGROUND_SECONDARY) ); 00409 00410 GfxContext.PopClippingRectangle(); 00411 // else 00412 // { 00413 // NString ValueString; 00414 // if(m_DynValueArray[index].m_ValueList.size() == 0) 00415 // ValueString = NString::Printf(TEXT("%.2f"), TEXT("0.00")); 00416 // else 00417 // ValueString = NString::Printf(TEXT("%.2f"), (*m_DynValueArray[index].m_ValueList.begin())); 00418 // GetPainter().PaintTextLineStatic(GfxContext, GetSysBoldFont(), m_GraphArea->GetGeometry(), ValueString, 0xFFFFFFFF, eAlignTextCenter); 00419 // } 00420 } 00421 00422 void TimeGraph::DrawContent (GraphicsEngine &GfxContext, bool force_draw) 00423 { 00424 } 00425 00426 void TimeGraph::PostDraw (GraphicsEngine &GfxContext, bool force_draw) 00427 { 00428 } 00429 00430 void TimeGraph::SetYAxisBounds (float minY, float maxY) 00431 { 00432 m_minY = minY; 00433 m_maxY = maxY; 00434 QueueDraw(); 00435 } 00436 00437 void TimeGraph::AddValue (float Value) 00438 { 00439 00440 } 00441 00442 t_u32 TimeGraph::AddGraph (Color PrimaryColor, Color SecondaryColor) 00443 { 00444 Graph graph (PrimaryColor, SecondaryColor); 00445 // Set an initial value; 00446 graph.Update (0.0f); 00447 t_u32 index = (t_u32) m_DynValueArray.size(); 00448 m_DynValueArray.push_back (graph); 00449 00450 return index; 00451 } 00452 00453 void TimeGraph::UpdateGraph (t_u32 index, float Value) 00454 { 00455 nuxAssert (index < m_DynValueArray.size() ); 00456 00457 if (index >= m_DynValueArray.size() ) 00458 return; 00459 00460 m_DynValueArray[index].Update (Value); 00461 QueueDraw(); 00462 } 00463 00464 void TimeGraph::ShowGraphStyle() 00465 { 00466 m_Option = SHOW_GRAPH; 00467 QueueDraw(); 00468 } 00469 00470 void TimeGraph::ShowColumnStyle() 00471 { 00472 m_Option = SHOW_COLUMN; 00473 QueueDraw(); 00474 } 00475 00476 void TimeGraph::ShowNumberStyle() 00477 { 00478 m_Option = SHOW_VALUE; 00479 QueueDraw(); 00480 } 00481 00482 00483 }