1 
2 ///////////////////////////////////////////////////////////
3 //                                                       //
4 //                         SAGA                          //
5 //                                                       //
6 //      System for Automated Geoscientific Analyses      //
7 //                                                       //
8 //                    User Interface                     //
9 //                                                       //
10 //                    Program: SAGA                      //
11 //                                                       //
12 //-------------------------------------------------------//
13 //                                                       //
14 //                VIEW_Table_Diagram.cpp                 //
15 //                                                       //
16 //          Copyright (C) 2005 by Olaf Conrad            //
17 //                                                       //
18 //-------------------------------------------------------//
19 //                                                       //
20 // This file is part of 'SAGA - System for Automated     //
21 // Geoscientific Analyses'. SAGA is free software; you   //
22 // can redistribute it and/or modify it under the terms  //
23 // of the GNU General Public License as published by the //
24 // Free Software Foundation, either version 2 of the     //
25 // License, or (at your option) any later version.       //
26 //                                                       //
27 // SAGA is distributed in the hope that it will be       //
28 // useful, but WITHOUT ANY WARRANTY; without even the    //
29 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
30 // PARTICULAR PURPOSE. See the GNU General Public        //
31 // License for more details.                             //
32 //                                                       //
33 // You should have received a copy of the GNU General    //
34 // Public License along with this program; if not, see   //
35 // <http://www.gnu.org/licenses/>.                       //
36 //                                                       //
37 //-------------------------------------------------------//
38 //                                                       //
39 //    contact:    Olaf Conrad                            //
40 //                Institute of Geography                 //
41 //                University of Hamburg                  //
42 //                Germany                                //
43 //                                                       //
44 //    e-mail:     oconrad@saga-gis.org                   //
45 //                                                       //
46 ///////////////////////////////////////////////////////////
47 
48 //---------------------------------------------------------
49 #include <wx/wx.h>
50 #include <wx/window.h>
51 #include <wx/scrolwin.h>
52 #include <wx/clipbrd.h>
53 
54 #include <saga_gdi/sgdi_helper.h>
55 
56 #include "res_commands.h"
57 #include "res_controls.h"
58 #include "res_images.h"
59 #include "res_dialogs.h"
60 
61 #include "helper.h"
62 
63 #include "wksp_table.h"
64 
65 #include "view_table_diagram.h"
66 
67 
68 ///////////////////////////////////////////////////////////
69 //														 //
70 //														 //
71 //														 //
72 ///////////////////////////////////////////////////////////
73 
74 //---------------------------------------------------------
75 class CVIEW_Table_Diagram_Control : public wxScrolledWindow
76 {
77 	friend CVIEW_Table_Diagram;
78 
79 public:
80 	CVIEW_Table_Diagram_Control(wxWindow *pParent, CWKSP_Table *pTable);
81 	virtual ~CVIEW_Table_Diagram_Control(void);
82 
83 	bool							Update_Diagram		(void);
84 
85 	bool							Set_Size			(const wxSize &Size);
86 	bool							Fit_Size			(void);
87 
88 	bool							Set_Zoom			(double Zoom);
89 	bool							Set_Zoom			(double Zoom, wxPoint Center);
90 
91 	bool							Set_Parameters		(void);
92 
93 	void							SaveToClipboard		(void);
94 
95 	virtual void					OnDraw				(wxDC &dc);
96 
97 	void							On_Size				(wxSizeEvent  &event);
98 	void							On_Mouse_LDown		(wxMouseEvent &event);
99 	void							On_Mouse_RDown		(wxMouseEvent &event);
100 	void							On_Mouse_Wheel		(wxMouseEvent &event);
101 	void							On_Key_Down			(wxKeyEvent   &event);
102 
103 
104 private:
105 
106 	int								m_xField;
107 
108 	double							m_xMin, m_xMax, m_yMin, m_yMax, m_yScale;
109 
110 	CSG_Array_Int					m_Fields;
111 
112 	CSG_Colors						m_Colors;
113 
114 	CSG_Parameters					m_Parameters;
115 
116 	CSG_Table						*m_pTable, m_Structure;
117 
118 	wxSize							m_Size;
119 
120 
121 	void							_Destroy				(void);
122 	bool							_Create					(void);
123 
124 	bool							_Initialize				(void);
125 
126 	static int						_On_Parameter_Changed	(CSG_Parameter *pParameter, int Flags);
127 
128 	int								_Get_Field_By_Name		(const CSG_String &sField);
129 
130 	void							_Draw					(wxDC &dc, wxRect r);
131 	void							_Draw_Frame				(wxDC &dc, wxRect r, double dx, double dy);
132 	void							_Draw_Legend			(wxDC &dc, wxRect r);
133 	void							_Draw_Points			(wxDC &dc, wxRect r, double dx, double dy, int iField, double Offset, double Scale);
134 	void							_Draw_Lines				(wxDC &dc, wxRect r, double dx, double dy, int iField, double Offset, double Scale);
135 	void							_Draw_Bars				(wxDC &dc, wxRect r, double dx, double dy, int iField, double Offset, double Scale);
136 
137 
138 	//-----------------------------------------------------
139 	DECLARE_CLASS(CVIEW_Table_Diagram_Control)
140 	DECLARE_EVENT_TABLE()
141 
142 };
143 
144 
145 ///////////////////////////////////////////////////////////
146 //														 //
147 ///////////////////////////////////////////////////////////
148 
149 //---------------------------------------------------------
150 IMPLEMENT_CLASS(CVIEW_Table_Diagram_Control, wxScrolledWindow);
151 
152 //---------------------------------------------------------
BEGIN_EVENT_TABLE(CVIEW_Table_Diagram_Control,wxScrolledWindow)153 BEGIN_EVENT_TABLE(CVIEW_Table_Diagram_Control, wxScrolledWindow)
154 	EVT_SIZE      (CVIEW_Table_Diagram_Control::On_Size)
155 	EVT_LEFT_DOWN (CVIEW_Table_Diagram_Control::On_Mouse_LDown)
156 	EVT_RIGHT_DOWN(CVIEW_Table_Diagram_Control::On_Mouse_RDown)
157 	EVT_MOUSEWHEEL(CVIEW_Table_Diagram_Control::On_Mouse_Wheel)
158 	EVT_KEY_DOWN  (CVIEW_Table_Diagram_Control::On_Key_Down)
159 END_EVENT_TABLE()
160 
161 
162 ///////////////////////////////////////////////////////////
163 //														 //
164 ///////////////////////////////////////////////////////////
165 
166 //---------------------------------------------------------
167 CVIEW_Table_Diagram_Control::CVIEW_Table_Diagram_Control(wxWindow *pParent, CWKSP_Table *pTable)
168 	: wxScrolledWindow(pParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxFULL_REPAINT_ON_RESIZE)
169 {
170 	SYS_Set_Color_BG_Window(this);
171 
172 	m_pTable	= pTable->Get_Table();
173 
174 	_Initialize();
175 }
176 
177 //---------------------------------------------------------
~CVIEW_Table_Diagram_Control(void)178 CVIEW_Table_Diagram_Control::~CVIEW_Table_Diagram_Control(void)
179 {
180 	_Destroy();
181 }
182 
183 
184 ///////////////////////////////////////////////////////////
185 //														 //
186 ///////////////////////////////////////////////////////////
187 
188 //---------------------------------------------------------
Set_Parameters(void)189 bool CVIEW_Table_Diagram_Control::Set_Parameters(void)
190 {
191 	double	Ratio	= m_Parameters("FIX_RATIO")->asBool() ? m_Parameters("RATIO")->asDouble() : 0.;
192 
193 	if( DLG_Parameters(&m_Parameters) && _Create() )
194 	{
195 		if( ((Ratio == 0.) == m_Parameters("FIX_RATIO")->asBool()) || ((Ratio != 0.) && Ratio != m_Parameters("RATIO")->asDouble()) )
196 		{
197 			Fit_Size();
198 		}
199 
200 		return( true );
201 	}
202 
203 	return( false );
204 }
205 
206 //---------------------------------------------------------
Update_Diagram(void)207 bool CVIEW_Table_Diagram_Control::Update_Diagram(void)
208 {
209 	return( m_Structure.is_Compatible(m_pTable, true) ? _Create() : _Initialize() );
210 }
211 
212 
213 ///////////////////////////////////////////////////////////
214 //														 //
215 ///////////////////////////////////////////////////////////
216 
217 //---------------------------------------------------------
218 #define MIN_SIZE		100
219 
220 #define SCROLL_RATE		5
221 
222 #define SCROLL_BAR_DX	wxSystemSettings::GetMetric(wxSYS_VSCROLL_X)
223 #define SCROLL_BAR_DY	wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y)
224 
225 //---------------------------------------------------------
Fit_Size(void)226 bool CVIEW_Table_Diagram_Control::Fit_Size(void)
227 {
228 	wxSize	Size(GetParent()->GetClientSize());
229 
230 	Size.x	-= (int)(1.5 * SCROLL_BAR_DX);
231 	Size.y	-= (int)(1.5 * SCROLL_BAR_DY);
232 
233 	if( m_Parameters("FIX_RATIO")->asBool() )
234 	{
235 		double	Ratio	= m_Parameters("RATIO")->asDouble();
236 
237 		if( Size.x / (double)Size.y > Ratio )
238 		{
239 			Size.x = (int)(Size.y * Ratio);
240 		}
241 		else
242 		{
243 			Size.y = (int)(Size.x / Ratio);
244 		}
245 	}
246 
247 	return( Set_Size(Size) );
248 }
249 
250 //---------------------------------------------------------
Set_Size(const wxSize & Size)251 bool CVIEW_Table_Diagram_Control::Set_Size(const wxSize &Size)
252 {
253 	static bool bSizing = false;
254 
255 	if( !bSizing && Size.x >= MIN_SIZE && Size.y >= MIN_SIZE )
256 	{
257 		if( Size.x != m_Size.x || Size.y != m_Size.y )
258 		{
259 			bSizing	= true;
260 
261 			m_Size	= Size;
262 
263 			SetScrollbars(SCROLL_RATE, SCROLL_RATE,
264 				(m_Size.x + SCROLL_BAR_DX) / SCROLL_RATE,
265 				(m_Size.y + SCROLL_BAR_DY) / SCROLL_RATE
266 			);
267 
268 			Refresh(false);
269 
270 			bSizing	= false;
271 		}
272 
273 		return( true );
274 	}
275 
276 	return( false );
277 }
278 
279 //---------------------------------------------------------
Set_Zoom(double Zoom)280 bool CVIEW_Table_Diagram_Control::Set_Zoom(double Zoom)
281 {
282 	return( Set_Zoom(Zoom, wxPoint(GetClientSize().x / 2, GetClientSize().y / 2)) );
283 }
284 
Set_Zoom(double Zoom,wxPoint Center)285 bool CVIEW_Table_Diagram_Control::Set_Zoom(double Zoom, wxPoint Center)
286 {
287 	if( Zoom > 0. )
288 	{
289 		int x, y; GetViewStart(&x, &y);
290 
291 		x	= (int)((Zoom * (x * SCROLL_RATE + Center.x) - GetClientSize().x / 2) / SCROLL_RATE);
292 		y	= (int)((Zoom * (y * SCROLL_RATE + Center.y) - GetClientSize().y / 2) / SCROLL_RATE);
293 
294 		if( Set_Size(wxSize((int)(m_Size.x * Zoom), (int)(m_Size.y * Zoom))) )
295 		{
296 			Scroll(x, y);
297 
298 			return( true );
299 		}
300 	}
301 
302 	return( false );
303 }
304 
305 
306 ///////////////////////////////////////////////////////////
307 //														 //
308 ///////////////////////////////////////////////////////////
309 
310 //---------------------------------------------------------
On_Size(wxSizeEvent & WXUNUSED (event))311 void CVIEW_Table_Diagram_Control::On_Size(wxSizeEvent &WXUNUSED(event))
312 {
313 	if( m_Parameters("FIT_SIZE") && m_Parameters("FIT_SIZE")->asBool() )
314 	{
315 		Fit_Size();
316 	}
317 }
318 
319 //---------------------------------------------------------
On_Mouse_LDown(wxMouseEvent & event)320 void CVIEW_Table_Diagram_Control::On_Mouse_LDown(wxMouseEvent &event)
321 {
322 	event.Skip();
323 }
324 
325 //---------------------------------------------------------
On_Mouse_RDown(wxMouseEvent & event)326 void CVIEW_Table_Diagram_Control::On_Mouse_RDown(wxMouseEvent &event)
327 {
328 	wxMenu	Menu;
329 
330 	CMD_Menu_Add_Item(&Menu, false, ID_CMD_DIAGRAM_TO_CLIPBOARD);
331 	Menu.AppendSeparator();
332 	CMD_Menu_Add_Item(&Menu, false, ID_CMD_DIAGRAM_SIZE_FIT);
333 	CMD_Menu_Add_Item(&Menu, false, ID_CMD_DIAGRAM_SIZE_INC);
334 	CMD_Menu_Add_Item(&Menu, false, ID_CMD_DIAGRAM_SIZE_DEC);
335 	CMD_Menu_Add_Item(&Menu,  true, ID_CMD_DIAGRAM_LEGEND);
336 	Menu.AppendSeparator();
337 	CMD_Menu_Add_Item(&Menu, false, ID_CMD_DIAGRAM_PARAMETERS);
338 
339 	PopupMenu(&Menu, event.GetPosition());
340 }
341 
342 //---------------------------------------------------------
On_Mouse_Wheel(wxMouseEvent & event)343 void CVIEW_Table_Diagram_Control::On_Mouse_Wheel(wxMouseEvent &event)
344 {
345 	Set_Zoom(event.GetWheelRotation() > 0 ? 1.2 : 1. / 1.2, event.GetPosition());
346 }
347 
348 //---------------------------------------------------------
On_Key_Down(wxKeyEvent & event)349 void CVIEW_Table_Diagram_Control::On_Key_Down(wxKeyEvent &event)
350 {
351 	switch( event.GetKeyCode() )
352 	{
353 	default: event.Skip(); break;
354 
355 	case WXK_PAGEDOWN: Set_Zoom(     1.2); break;
356 	case WXK_PAGEUP  : Set_Zoom(1. / 1.2); break;
357 
358 	case WXK_DOWN : { wxPoint p(GetViewStart()); Scroll(p.x, p.y + SCROLL_RATE); } break;
359 	case WXK_UP   : { wxPoint p(GetViewStart()); Scroll(p.x, p.y - SCROLL_RATE); } break;
360 
361 	case WXK_LEFT : { wxPoint p(GetViewStart()); Scroll(p.x - SCROLL_RATE, p.y); } break;
362 	case WXK_RIGHT: { wxPoint p(GetViewStart()); Scroll(p.x + SCROLL_RATE, p.y); } break;
363 
364 	case 'C':
365 		if( event.GetModifiers() == wxMOD_CONTROL )
366 		{
367 			SaveToClipboard();
368 		}
369 		break;
370 	}
371 }
372 
373 
374 ///////////////////////////////////////////////////////////
375 //														 //
376 ///////////////////////////////////////////////////////////
377 
378 //---------------------------------------------------------
OnDraw(wxDC & dc)379 void CVIEW_Table_Diagram_Control::OnDraw(wxDC &dc)
380 {
381 	wxBitmap	Bmp(m_Size);
382 	wxMemoryDC	dc_Bmp(Bmp);
383 
384 	dc_Bmp.SetBackground(*wxWHITE_BRUSH);
385 	dc_Bmp.Clear();
386 
387 	_Draw(dc_Bmp, m_Size);
388 
389 	dc_Bmp.SelectObject(wxNullBitmap);
390 
391 	dc.DrawBitmap(Bmp, 0, 0);
392 }
393 
394 
395 ///////////////////////////////////////////////////////////
396 //														 //
397 ///////////////////////////////////////////////////////////
398 
399 //---------------------------------------------------------
SaveToClipboard(void)400 void CVIEW_Table_Diagram_Control::SaveToClipboard(void)
401 {
402 	Set_Buisy_Cursor(true);
403 
404 	wxBitmap	Bmp(m_Size);
405 	wxMemoryDC	dc_Bmp(Bmp);
406 
407 	dc_Bmp.SetBackground(*wxWHITE_BRUSH);
408 	dc_Bmp.Clear();
409 
410 	_Draw(dc_Bmp, wxRect(m_Size));
411 
412 	dc_Bmp.SelectObject(wxNullBitmap);
413 
414 	if( wxTheClipboard->Open() )
415 	{
416 		wxBitmapDataObject	*pBmp	= new wxBitmapDataObject;
417 		pBmp->SetBitmap(Bmp);
418 		wxTheClipboard->SetData(pBmp);
419 		wxTheClipboard->Close();
420 	}
421 
422 	Set_Buisy_Cursor(false);
423 }
424 
425 
426 ///////////////////////////////////////////////////////////
427 //														 //
428 ///////////////////////////////////////////////////////////
429 
430 //---------------------------------------------------------
_Destroy(void)431 void CVIEW_Table_Diagram_Control::_Destroy(void)
432 {
433 	m_Fields.Destroy();
434 }
435 
436 //---------------------------------------------------------
_Create(void)437 bool CVIEW_Table_Diagram_Control::_Create(void)
438 {
439 	_Destroy();
440 
441 	//-----------------------------------------------------
442 	if( m_pTable && m_pTable->Get_Field_Count() > 0 )
443 	{
444 		m_xField	= _Get_Field_By_Name(m_Parameters("X_FIELD")->asString());
445 
446 		if( m_xField < 0 || m_pTable->Get_Range(m_xField) <= 0. )
447 		{
448 			m_xMin		= 1;
449 			m_xMax		= 1 + m_pTable->Get_Count();
450 			m_xField	= -1;
451 		}
452 		else if( m_pTable->Get_Field_Type(m_xField) == SG_DATATYPE_Date )
453 		{
454 			m_xMin		= m_pTable->Get_Minimum(m_xField);
455 			m_xMax		= m_pTable->Get_Maximum(m_xField);
456 		}
457 		else
458 		{
459 			m_xMin		= m_pTable->Get_Minimum(m_xField);
460 			m_xMax		= m_pTable->Get_Maximum(m_xField);
461 		}
462 
463 		//-------------------------------------------------
464 		bool	bScaling	= m_Parameters("Y_SCALING")->asBool();
465 
466 		for(int iField=0; iField<m_pTable->Get_Field_Count(); iField++)
467 		{
468 			if( SG_Data_Type_is_Numeric(m_pTable->Get_Field_Type(iField))
469 			&&  m_Parameters(CSG_String::Format("FIELD_%d", iField))->asBool() )
470 			{
471 				m_Fields	+= iField;
472 
473 				m_Colors.Set_Color(iField, m_Parameters(CSG_String::Format("COLOR_%d" , iField))->asColor());
474 
475 				double Offset = bScaling ? m_Parameters(CSG_String::Format("OFFSET_%d", iField))->asDouble() : 0.;
476 				double Scale  = bScaling ? m_Parameters(CSG_String::Format("SCALE_%d" , iField))->asDouble() : 1.;
477 
478 				double yMin = Scale * m_pTable->Get_Minimum(iField) + Offset;
479 				double yMax = Scale * m_pTable->Get_Maximum(iField) + Offset;
480 
481 				if( yMin > yMax ) { double y = yMin; yMin = yMax; yMax = y; }
482 
483 				if( m_Fields.Get_Size() == 1 )
484 				{
485 					m_yMin	= yMin;
486 					m_yMax	= yMax;
487 				}
488 				else
489 				{
490 					if( m_yMin	> yMin )
491 						m_yMin	= yMin;
492 
493 					if( m_yMax	< yMax )
494 						m_yMax	= yMax;
495 				}
496 			}
497 		}
498 
499 		//-------------------------------------------------
500 		if( m_Parameters("Y_MIN_FIX")->asBool() )
501 		{
502 			m_yMin	= m_Parameters("Y_MIN_VAL")->asDouble();
503 		}
504 
505 		m_yScale	= m_Parameters("Y_SCALE_TO_X")->asBool() ? m_Parameters("Y_SCALE_RATIO")->asDouble() : 0.;
506 
507 		if( m_yScale > 0. )
508 		{
509 			m_yMax	= m_yMin + (m_xMax - m_xMin) / m_yScale;
510 		}
511 		else if( m_Parameters("Y_MAX_FIX")->asBool() )
512 		{
513 			m_yMax	= m_Parameters("Y_MAX_VAL")->asDouble();
514 		}
515 	}
516 
517 	if( !m_Size.GetWidth() || !m_Size.GetHeight() )
518 	{
519 		SetSize(GetParent()->GetClientSize());
520 	}
521 
522 	Refresh(false);
523 
524 	return( m_Fields.Get_Size() > 0 );
525 }
526 
527 
528 ///////////////////////////////////////////////////////////
529 //														 //
530 ///////////////////////////////////////////////////////////
531 
532 //---------------------------------------------------------
_Initialize(void)533 bool CVIEW_Table_Diagram_Control::_Initialize(void)
534 {
535 	_Destroy();
536 
537 	if( !m_pTable || m_pTable->Get_Field_Count() < 1 || m_pTable->Get_Count() < 1 )
538 	{
539 		return( false );
540 	}
541 
542 	//-----------------------------------------------------
543 	#define CHART_TYPES _TL("bars"), _TL("lines"), _TL("points"), _TL("points connected with lines"), _TL("select a chart type for each attribute")
544 
545 	CSG_String	sFields_All, sFields_Num; int nFields_Num = 0;
546 
547 	m_Structure.Create(m_pTable);
548 
549 	m_Colors.Set_Count(m_pTable->Get_Field_Count());
550 
551 	m_Parameters.Create(_TL("Properties"));
552 	m_Parameters.Set_Callback_On_Parameter_Changed(_On_Parameter_Changed);
553 
554 	//-----------------------------------------------------
555 	m_Parameters.Add_Bool("", "SHOW_FIELDS", _TL("Show/Hide All Attributes"), _TL("Show or hide all attributes."));
556 
557 	for(int iField=0; iField<m_pTable->Get_Field_Count(); iField++)
558 	{
559 		if( SG_Data_Type_is_Numeric(m_pTable->Get_Field_Type(iField)) )
560 		{
561 			CSG_String	ID; ID.Printf("FIELD_%d", iField);
562 
563 			m_Parameters.Add_Bool("SHOW_FIELDS", ID, m_pTable->Get_Field_Name(iField), _TL("Show"), false);
564 			m_Parameters.Add_Color (ID, CSG_String::Format("COLOR_%d" , iField), _TL("Color" ), "", m_Colors.Get_Color(iField));
565 			m_Parameters.Add_Choice(ID, CSG_String::Format("TYPE_%d"  , iField), _TL("Type"  ), "", CSG_String::Format("%s|%s|%s|%s", CHART_TYPES), 1);
566 			m_Parameters.Add_Double(ID, CSG_String::Format("OFFSET_%d", iField), _TL("Offset"), "", 0.);
567 			m_Parameters.Add_Double(ID, CSG_String::Format("SCALE_%d" , iField), _TL("Scale" ), "", 1.);
568 		}
569 
570 		if( SG_Data_Type_is_Numeric(m_pTable->Get_Field_Type(iField))
571 		||  m_pTable->Get_Field_Type(iField) == SG_DATATYPE_Date )
572 		{
573 			sFields_Num	+= CSG_String::Format("%s|", m_pTable->Get_Field_Name(iField));
574 			nFields_Num	++;
575 		}
576 
577 		sFields_All	+= CSG_String::Format("%s|", m_pTable->Get_Field_Name(iField));
578 	}
579 
580 	sFields_Num	+= CSG_String::Format("<%s>", _TL("none"));
581 	sFields_All	+= CSG_String::Format("<%s>", _TL("none"));
582 
583 	//-----------------------------------------------------
584 	m_Parameters.Add_Node  (""            , "NODE_X"            , _TL("X Axis"            ), _TL(""));
585 	m_Parameters.Add_Choice("NODE_X"      , "X_FIELD"           , _TL("Values"            ), _TL(""), sFields_Num, nFields_Num);
586 	m_Parameters.Add_Choice("NODE_X"      , "X_LABEL"           , _TL("Label"             ), _TL(""), sFields_All, m_pTable->Get_Field_Count());
587 
588 	//-----------------------------------------------------
589 	m_Parameters.Add_Node  (""            , "NODE_Y"            , _TL("Y Axis"            ), _TL(""));
590 	m_Parameters.Add_Bool  ("NODE_Y"      , "Y_SCALE_TO_X"      , _TL("Scale"             ), _TL("Scale Y axis to match X axis by a factor (ratio)."), false);
591 	m_Parameters.Add_Double("Y_SCALE_TO_X", "Y_SCALE_RATIO"     , _TL("Ratio"             ), _TL(""), 1., 0., true);
592 	m_Parameters.Add_Bool  ("NODE_Y"      , "Y_MIN_FIX"	        , _TL("Fix Minimum"       ), _TL(""), false);
593 	m_Parameters.Add_Double("Y_MIN_FIX"   , "Y_MIN_VAL"	        , _TL("Minimum"           ), _TL(""), 0.);
594 	m_Parameters.Add_Bool  ("NODE_Y"      , "Y_MAX_FIX"	        , _TL("Fix Maximum"       ), _TL(""), false);
595 	m_Parameters.Add_Double("Y_MAX_FIX"   , "Y_MAX_VAL"         , _TL("Maximum"           ), _TL(""), 1000.);
596 	m_Parameters.Add_Bool  ("NODE_Y"      , "Y_SCALING"         , _TL("Edit Scaling"      ), _TL("Edit offset and scaling for each attribute."), false);
597 
598 	//-----------------------------------------------------
599 	m_Parameters.Add_Font  (""            , "FONT"              , _TL("Font"              ), _TL(""));
600 
601 	m_Parameters.Add_Bool  (""            , "LEGEND"            , _TL("Legend"            ), _TL(""), true);
602 	m_Parameters.Add_Int   ("LEGEND"      , "LEGEND_WIDTH"      , _TL("Width"             ), _TL("Percent"), 15, 0, true, 50, true);
603 
604 	//-----------------------------------------------------
605 	m_Parameters.Add_Node  (""            , "NODE_CHART"        , _TL("Chart Settings"    ), _TL(""));
606 
607 	m_Parameters.Add_Choice("NODE_CHART"  , "TYPE"              , _TL("Chart Type"        ), _TL(""), CSG_String::Format("%s|%s|%s|%s|%s", CHART_TYPES), 4);
608 
609 //	m_Parameters.Add_Node  ("NODE_CHART"  , "NODE_BARS"         , _TL("Bars"              ), _TL(""));
610 //	m_Parameters.Add_Choice("NODE_BARS"   , "BARS_OFFSET"       , _TL("Offset"            ), _TL(""), CSG_String::Format("%s|%s|%s", _TL("origin"), _TL("bottom"), _TL("top")), 0);
611 
612 	m_Parameters.Add_Node  ("NODE_CHART"  , "NODE_LINES"        , _TL("Lines"             ), _TL(""));
613 	m_Parameters.Add_Int   ("NODE_LINES"  , "LINES_SIZE"        , _TL("Size"              ), _TL(""), 1, 1, true);
614 
615 	m_Parameters.Add_Node  ("NODE_CHART"  , "NODE_POINTS"       , _TL("Points"            ), _TL(""));
616 	m_Parameters.Add_Int   ("NODE_POINTS" , "POINTS_SIZE"       , _TL("Size"              ), _TL(""), 2, 1, true);
617 	m_Parameters.Add_Bool  ("NODE_POINTS" , "POINTS_OUTLINE"    , _TL("Outline"           ), _TL(""), false);
618 	m_Parameters.Add_Choice("NODE_POINTS" , "POINTS_COLOR_FIELD", _TL("Color by Attribute"), _TL(""), sFields_Num, nFields_Num);
619 	m_Parameters.Add_Colors("NODE_POINTS" , "POINTS_COLORS"     , _TL("Colors"            ), _TL(""));
620 
621 	//-----------------------------------------------------
622 	m_Parameters.Add_Node  (""            , "NODE_FRAME"        , _TL("Frame"             ), _TL(""));
623 	m_Parameters.Add_Choice("NODE_FRAME"  , "FRAME_FULL"        , _TL("Draw Frame"        ), _TL(""), CSG_String::Format("%s|%s", _TL("all sides"), _TL("left/bottom")), 1);
624 	m_Parameters.Add_Bool  ("NODE_FRAME"  , "AXES_ORIGINS"      , _TL("Show Origins"      ), _TL(""), false);
625 	m_Parameters.Add_Bool  ("NODE_FRAME"  , "FIT_SIZE"          , _TL("Fit Size to Window"), _TL("Fit diagram's frame size to the parent window, when its size has changed."), true);
626 	m_Parameters.Add_Bool  ("NODE_FRAME"  , "FIX_RATIO"         , _TL("Fix Ratio"         ), _TL("Use a fix width to height ratio."), false);
627 	m_Parameters.Add_Double("FIX_RATIO"   , "RATIO"             , _TL("Ratio"             ), _TL(""), (1. + sqrt(5.)) / 2., 0.01, true, 100., true);
628 
629 	m_Parameters.Add_Node  (""            , "NODE_MARGINS"      , _TL("Frame Margins"     ), _TL(""));
630 	m_Parameters.Add_Int   ("NODE_MARGINS", "MARGIN_LEFT"       , _TL("Left"              ), _TL("Pixels"), 50, 0, true);
631 	m_Parameters.Add_Int   ("NODE_MARGINS", "MARGIN_RIGHT"      , _TL("Right"             ), _TL("Pixels"), 10, 0, true);
632 	m_Parameters.Add_Int   ("NODE_MARGINS", "MARGIN_TOP"        , _TL("Top"               ), _TL("Pixels"), 10, 0, true);
633 	m_Parameters.Add_Int   ("NODE_MARGINS", "MARGIN_BOTTOM"     , _TL("Bottom"            ), _TL("Pixels"), 50, 0, true);
634 
635 	return( _Create() && Fit_Size() );
636 }
637 
638 //---------------------------------------------------------
_On_Parameter_Changed(CSG_Parameter * pParameter,int Flags)639 int CVIEW_Table_Diagram_Control::_On_Parameter_Changed(CSG_Parameter *pParameter, int Flags)
640 {
641 	CSG_Parameters	*pParameters	= pParameter ? pParameter->Get_Parameters() : NULL;
642 
643 	if( !pParameters )
644 	{
645 		return( 0 );
646 	}
647 
648 	//-----------------------------------------------------
649 	if( Flags & PARAMETER_CHECK_VALUES )
650 	{
651 		if( pParameter->Cmp_Identifier("SHOW_FIELDS") )
652 		{
653 			bool bDifferent = (*pParameters)("TYPE")->asInt() >= 4;
654 
655 			for(int i=0; i<pParameter->Get_Children_Count(); i++)
656 			{
657 				pParameter->Get_Child(i)->Set_Value                (pParameter->asBool());
658 				pParameter->Get_Child(i)->Get_Child(0)->Set_Enabled(pParameter->asBool());
659 				pParameter->Get_Child(i)->Get_Child(1)->Set_Enabled(pParameter->asBool() && bDifferent);
660 			}
661 		}
662 	}
663 
664 	//-----------------------------------------------------
665 	if( Flags & PARAMETER_CHECK_ENABLE )
666 	{
667 		if( pParameter->Cmp_Identifier("TYPE") )
668 		{
669 		//	pParameters->Set_Enabled("NODE_BARS"    , pParameter->asInt() >= 4 || pParameter->asInt() == 0                            );
670 			pParameters->Set_Enabled("NODE_LINES"   , pParameter->asInt() >= 4 || pParameter->asInt() == 1 || pParameter->asInt() == 3);
671 			pParameters->Set_Enabled("NODE_POINTS"  , pParameter->asInt() >= 4 || pParameter->asInt() == 2 || pParameter->asInt() == 3);
672 
673 			CSG_Parameter *pFields = (*pParameters)("SHOW_FIELDS");
674 
675 			for(int i=0; i<pFields->Get_Children_Count(); i++)
676 			{
677 				CSG_Parameter *pField = pFields->Get_Child(i);
678 
679 				pField->Get_Child(1)->Set_Enabled(pField->asBool() && pParameter->asInt() >= 4);
680 			}
681 		}
682 
683 		if( pParameter->Cmp_Identifier("Y_SCALING") )
684 		{
685 			CSG_Parameter *pFields = (*pParameters)("SHOW_FIELDS");
686 
687 			for(int i=0; i<pFields->Get_Children_Count(); i++)
688 			{
689 				CSG_Parameter *pField = pFields->Get_Child(i);
690 
691 				pField->Get_Child(2)->Set_Enabled(pField->asBool() && pParameter->asBool());
692 				pField->Get_Child(3)->Set_Enabled(pField->asBool() && pParameter->asBool());
693 			}
694 		}
695 
696 		if( pParameter->Cmp_Identifier("POINTS_COLOR_FIELD") )
697 		{
698 			pParameters->Set_Enabled("POINTS_COLORS", pParameter->asInt() < pParameter->asChoice()->Get_Count() - 1);
699 		}
700 
701 		if( pParameter->Cmp_Identifier("LEGEND") )
702 		{
703 			pParameters->Set_Enabled("LEGEND_WIDTH", pParameter->asBool());
704 		}
705 
706 		if( pParameter->Cmp_Identifier("FIX_RATIO") )
707 		{
708 			pParameters->Set_Enabled("RATIO", pParameter->asBool());
709 		}
710 
711 		if( pParameter->Cmp_Identifier("X_FIELD") )
712 		{
713 			bool	bNone	= pParameter->asInt() >= pParameter->asChoice()->Get_Count() - 1;
714 
715 			pParameters->Set_Enabled("Y_SCALE_TO_X", bNone == false);
716 			pParameters->Set_Enabled("Y_MAX_FIX"   , bNone || (*pParameters)("Y_SCALE_TO_X")->asBool() == false);
717 		}
718 
719 		if( pParameter->Cmp_Identifier("Y_SCALE_TO_X") )
720 		{
721 			pParameters->Set_Enabled("Y_SCALE_RATIO", pParameter->asBool() ==  true);
722 			pParameters->Set_Enabled("Y_MAX_FIX"    , pParameter->asBool() == false);
723 		}
724 
725 		if( pParameter->Cmp_Identifier("Y_MIN_FIX") )
726 		{
727 			pParameters->Set_Enabled("Y_MIN_VAL"    , pParameter->asBool());
728 		}
729 
730 		if( pParameter->Cmp_Identifier("Y_MAX_FIX") )
731 		{
732 			pParameters->Set_Enabled("Y_MAX_VAL"    , pParameter->asBool());
733 		}
734 
735 		if( pParameter->Cmp_Identifier("X_FIELD") )
736 		{
737 			pParameters->Set_Enabled("X_LABEL"      , pParameter->asInt() >= pParameter->asChoice()->Get_Count() - 1);
738 		}
739 
740 		CSG_String	ID(pParameter->Get_Identifier());
741 
742 		if( ID.Find("FIELD_") == 0 )
743 		{
744 			pParameters->Set_Enabled("COLOR_"  + ID.AfterFirst('_'), pParameter->asBool());
745 			pParameters->Set_Enabled("TYPE_"   + ID.AfterFirst('_'), pParameter->asBool() && (*pParameters)("TYPE")->asInt() >= 4);
746 			pParameters->Set_Enabled("OFFSET_" + ID.AfterFirst('_'), pParameter->asBool() && (*pParameters)("Y_SCALING")->asBool());
747 			pParameters->Set_Enabled("SCALE_"  + ID.AfterFirst('_'), pParameter->asBool() && (*pParameters)("Y_SCALING")->asBool());
748 		}
749 	}
750 
751 	//-----------------------------------------------------
752 	return( 1 );
753 }
754 
755 
756 ///////////////////////////////////////////////////////////
757 //														 //
758 ///////////////////////////////////////////////////////////
759 
760 //---------------------------------------------------------
_Get_Field_By_Name(const CSG_String & sField)761 int CVIEW_Table_Diagram_Control::_Get_Field_By_Name(const CSG_String &sField)
762 {
763 	if( m_pTable )
764 	{
765 		for(int iField=0; iField<m_pTable->Get_Field_Count(); iField++)
766 		{
767 			if( sField.Cmp(m_pTable->Get_Field_Name(iField)) == 0 )
768 			{
769 				return( iField );
770 			}
771 		}
772 	}
773 
774 	return( -1 );
775 }
776 
777 
778 ///////////////////////////////////////////////////////////
779 //														 //
780 ///////////////////////////////////////////////////////////
781 
782 //---------------------------------------------------------
_Draw(wxDC & dc,wxRect rDC)783 void CVIEW_Table_Diagram_Control::_Draw(wxDC &dc, wxRect rDC)
784 {
785 	#define DO_ERROR(s)	Draw_Text(dc, TEXTALIGN_CENTER, rDC.GetLeft() + rDC.GetWidth() / 2, rDC.GetTop() + rDC.GetHeight() / 2, s); return;
786 
787 	dc.SetFont(Get_Font(m_Parameters("FONT")));
788 
789 	//-----------------------------------------------------
790 	if( m_Fields.Get_Size() < 1 )
791 	{
792 		DO_ERROR(_TL("invalid data set!"));
793 	}
794 
795 	//-----------------------------------------------------
796 	int	 wLegend = m_Parameters("LEGEND")->asBool() ? (int)(rDC.GetWidth () * 0.01 * m_Parameters("LEGEND_WIDTH")->asInt()) : 0;
797 
798 	wxRect	r(wxPoint(
799 		rDC.GetLeft  () + m_Parameters("MARGIN_LEFT"  )->asInt(),
800 		rDC.GetTop   () + m_Parameters("MARGIN_TOP"   )->asInt()), wxPoint(
801 		rDC.GetRight () - m_Parameters("MARGIN_RIGHT" )->asInt() - wLegend,
802 		rDC.GetBottom() - m_Parameters("MARGIN_BOTTOM")->asInt())
803 	);
804 
805 	//-----------------------------------------------------
806 	double	dy, dx;
807 
808 	if( m_xField < 0 )
809 	{
810 		dx	= r.GetWidth () / (double)m_pTable->Get_Count();
811 		dy	= r.GetHeight() / (m_yMax - m_yMin);
812 	}
813 	else if( m_xMin < m_xMax )
814 	{
815 		dx	= r.GetWidth () / (m_xMax - m_xMin);
816 
817 		if( m_yScale > 0. )
818 		{
819 			dy	= dx * m_yScale; m_yMax = m_yMin + r.GetHeight() / dy;
820 		}
821 		else if( m_yMin < m_yMax )
822 		{
823 			dy	= r.GetHeight() / (m_yMax - m_yMin);
824 		}
825 		else
826 		{
827 			DO_ERROR(_TL("invalid y range!"));
828 		}
829 	}
830 	else
831 	{
832 		DO_ERROR(_TL("invalid x range!"));
833 	}
834 
835 	//-----------------------------------------------------
836 	int Type = m_Parameters("TYPE")->asInt(); bool bDifferent = Type >= 4, bScaling = m_Parameters("Y_SCALING")->asBool();
837 
838 	for(size_t iField=0; iField<m_Fields.Get_Size(); iField++)
839 	{
840 		if( bDifferent )
841 		{
842 			CSG_Parameter *pParameter = m_Parameters(CSG_String::Format("TYPE_%d", m_Fields[iField]));
843 
844 			Type = pParameter ? pParameter->asInt() : -1;
845 		}
846 
847 		double Offset = bScaling ? m_Parameters(CSG_String::Format("OFFSET_%d", m_Fields[iField]))->asDouble() : 0.;
848 		double Scale  = bScaling ? m_Parameters(CSG_String::Format("SCALE_%d" , m_Fields[iField]))->asDouble() : 1.;
849 
850 		switch( Type )
851 		{
852 		case  0: _Draw_Bars  (dc, r, dx, dy, iField, Offset, Scale); break; // bars
853 		default: _Draw_Lines (dc, r, dx, dy, iField, Offset, Scale); break; // lines
854 		case  2: _Draw_Points(dc, r, dx, dy, iField, Offset, Scale); break; // points
855 		case  3: _Draw_Lines (dc, r, dx, dy, iField, Offset, Scale);        // points connected with lines
856 		         _Draw_Points(dc, r, dx, dy, iField, Offset, Scale); break;
857 		}
858 	}
859 
860 	//-----------------------------------------------------
861 	_Draw_Frame(dc, r, dx, dy);
862 
863 	if( wLegend > 0 )
864 	{
865 		r.SetLeft(rDC.GetRight() - wLegend);
866 		r.SetWidth(wLegend);
867 
868 		_Draw_Legend(dc, r);
869 	}
870 }
871 
872 //---------------------------------------------------------
_Draw_Frame(wxDC & dc,wxRect r,double dx,double dy)873 void CVIEW_Table_Diagram_Control::_Draw_Frame(wxDC &dc, wxRect r, double dx, double dy)
874 {
875 	const int	dyFont	= 12;
876 
877 	//-----------------------------------------------------
878 	dc.SetPen(*wxBLACK);
879 
880 	if( m_Parameters("FRAME_FULL")->asInt() == 0 )
881 	{
882 		Draw_Edge(dc, EDGE_STYLE_SIMPLE, r);
883 	}
884 	else
885 	{
886 		Draw_Edge(dc, EDGE_STYLE_SIMPLE, r.GetLeft(), r.GetBottom(), r.GetLeft (), r.GetTop   ());
887 		Draw_Edge(dc, EDGE_STYLE_SIMPLE, r.GetLeft(), r.GetBottom(), r.GetRight(), r.GetBottom());
888 	}
889 
890 	if( m_Parameters("AXES_ORIGINS")->asBool() )
891 	{
892 		if( m_xField >= 0 && m_xMin < 0 && 0 < m_xMax )
893 		{
894 			int x = r.GetLeft() + (int)(dx * (0 - m_xMin));
895 
896 			dc.DrawLine(x, r.GetBottom(), x, r.GetTop());
897 		}
898 
899 		if( m_yMin < 0 && 0 < m_yMax )
900 		{
901 			int y = r.GetBottom() - (int)(dy * (0 - m_yMin));
902 
903 			dc.DrawLine(r.GetLeft(), y, r.GetRight(), y);
904 		}
905 	}
906 
907 	//-----------------------------------------------------
908 	wxFont	Font(dc.GetFont());
909 	Font.SetPointSize((int)(0.7 * dyFont));
910 	dc.SetFont(Font);
911 
912 	//-----------------------------------------------------
913 	Draw_Scale(dc, wxRect(r.GetLeft() - 20, r.GetTop(), 20, r.GetHeight()),	// Y Axis
914 		m_yMin, m_yMax,
915 		false, false, false
916 	);
917 
918 	//-----------------------------------------------------
919 	if( m_xField >= 0 )	// numeric values
920 	{
921 		if( m_pTable->Get_Field_Type(m_xField) != SG_DATATYPE_Date )
922 		{
923 			Draw_Scale(dc, wxRect(r.GetLeft(), r.GetBottom(), r.GetWidth(), 20),
924 				m_xMin, m_xMax,
925 				true , true , true
926 			);
927 		}
928 		else // if( m_pTable->Get_Field_Type(m_xField) == SG_DATATYPE_Date )
929 		{
930 			double dStep  = 10 + dyFont;
931 			int    nSteps = r.GetWidth() / dStep;
932 			double dDay   = (m_xMax - m_xMin) / nSteps;
933 
934 			for(int iStep=0; iStep<=nSteps; iStep++)
935 			{
936 				int ix = r.GetLeft() + (int)(dStep * iStep);
937 
938 				dc.DrawLine(ix, r.GetBottom(), ix, r.GetBottom() + 5);	// tic
939 
940 				wxDateTime	Date(m_xMin + dDay * iStep);	// Julian Day Number
941 
942 				Draw_Text(dc, TEXTALIGN_CENTERRIGHT, ix, r.GetBottom() + 7, 45., Date.Format("%Y-%m-%d"));
943 			}
944 		}
945 	}
946 	else
947 	{
948 		int	iLabel	= m_Parameters("X_LABEL")->asInt();
949 
950 		if( iLabel < 0 || iLabel >= m_pTable->Get_Field_Count() )
951 		{
952 			Draw_Scale(dc, wxRect(r.GetLeft(), r.GetBottom(), r.GetWidth(), 20),
953 				1, m_pTable->Get_Count(),
954 				true , true , true
955 			);
956 		}
957 		else
958 		{
959 			int	iStep	= dx > dyFont ? 1 : (int)(1 + (10 + dyFont) / dx);
960 
961 			for(int iRecord=0; iRecord<m_pTable->Get_Count(); iRecord+=iStep)
962 			{
963 				int	ix	= r.GetLeft() + (int)(dx * iRecord);
964 
965 				dc.DrawLine(ix, r.GetBottom(), ix, r.GetBottom() + 5);
966 
967 				CSG_Table_Record *pRecord = m_pTable->Get_Record_byIndex(iRecord);
968 
969 				Draw_Text(dc, TEXTALIGN_CENTERRIGHT, ix, r.GetBottom() + 7, 45., pRecord->asString(iLabel));
970 			}
971 		}
972 	}
973 }
974 
975 //---------------------------------------------------------
_Draw_Legend(wxDC & dc,wxRect r)976 void CVIEW_Table_Diagram_Control::_Draw_Legend(wxDC &dc, wxRect r)
977 {
978 	int	dyFont	= (int)(0.08 * r.GetWidth());
979 	int	dyBox	= dyFont + 4;
980 	int	dxBox	= dyFont * 2;
981 
982 	const int minMargin = 10;
983 
984 	r.SetTopLeft(wxPoint(r.GetLeft() + minMargin, r.GetBottom() - m_Fields.Get_Size() * dyBox));
985 
986 	wxFont	Font(dc.GetFont());
987 	Font.SetPointSize(dyFont);
988 	dc.SetFont(Font);
989 
990 	dc.SetPen(*wxBLACK_PEN);
991 
992 	//-----------------------------------------------------
993 	for(size_t iField=0; iField<m_Fields.Get_Size(); iField++)
994 	{
995 		wxRect	rBox(r.GetLeft(), r.GetTop() + iField * dyBox, dxBox, dyBox);
996 		wxBrush	Brush(dc.GetBrush());
997 		Brush.SetColour(Get_Color_asWX(m_Colors.Get_Color(m_Fields[iField])));
998 		dc.SetBrush(Brush);
999 		dc.DrawRectangle(rBox.GetX(), rBox.GetY() + 4, rBox.GetWidth(), rBox.GetHeight() - 4);
1000 		dc.DrawText(m_pTable->Get_Field_Name(m_Fields[iField]), rBox.GetRight() + 5, rBox.GetTop());
1001 	}
1002 }
1003 
1004 
1005 ///////////////////////////////////////////////////////////
1006 //														 //
1007 ///////////////////////////////////////////////////////////
1008 
1009 //---------------------------------------------------------
1010 #define DRAW_GET_XPOS	(r.GetLeft  () + (int)(dx * (m_xField >= 0 ? (pRecord->asDouble(m_xField) - m_xMin) : (double)iRecord)))
1011 #define DRAW_GET_YPOS	(r.GetBottom() - (int)(dy * ((Scale * pRecord->asDouble(iField) + Offset) - m_yMin)))
1012 
1013 //---------------------------------------------------------
_Draw_Points(wxDC & dc,wxRect r,double dx,double dy,int iField,double Offset,double Scale)1014 void CVIEW_Table_Diagram_Control::_Draw_Points(wxDC &dc, wxRect r, double dx, double dy, int iField, double Offset, double Scale)
1015 {
1016 	bool	bOutline	= m_Parameters("POINTS_OUTLINE")->asBool();
1017 	int		Size		= m_Parameters("POINTS_SIZE"   )->asInt();
1018 	int		zField		= _Get_Field_By_Name(m_Parameters("POINTS_COLOR_FIELD")->asString());
1019 
1020 	iField	= m_Fields[iField];
1021 
1022 	if( zField < 0 )
1023 	{
1024 		dc.SetPen  (wxPen  (bOutline ? *wxBLACK : Get_Color_asWX(m_Colors.Get_Color(iField))));
1025 		dc.SetBrush(wxBrush(                      Get_Color_asWX(m_Colors.Get_Color(iField))));
1026 
1027 		for(int iRecord=0; iRecord<m_pTable->Get_Count(); iRecord++)
1028 		{
1029 			CSG_Table_Record	*pRecord	= m_pTable->Get_Record_byIndex(iRecord);
1030 
1031 			if( !pRecord->is_NoData(iField) && (m_pTable->Get_Selection_Count() < 1 || pRecord->is_Selected()) )
1032 			{
1033 				dc.DrawCircle(DRAW_GET_XPOS, DRAW_GET_YPOS, Size);
1034 			}
1035 		}
1036 	}
1037 	else
1038 	{
1039 		if( bOutline )
1040 		{
1041 			dc.SetPen(wxPen(Get_Color_asWX(m_Colors.Get_Color(iField))));
1042 		}
1043 
1044 		CSG_Colors	*pColors	= m_Parameters("POINTS_COLORS")->asColors();
1045 		double		zMin		= m_pTable->Get_Minimum(zField);
1046 		double		dz			= pColors->Get_Count() / m_pTable->Get_Range(zField);
1047 
1048 		for(int iRecord=0; iRecord<m_pTable->Get_Count(); iRecord++)
1049 		{
1050 			CSG_Table_Record	*pRecord	= m_pTable->Get_Record_byIndex(iRecord);
1051 
1052 			if( !pRecord->is_NoData(iField) && (m_pTable->Get_Selection_Count() < 1 || pRecord->is_Selected()) )
1053 			{
1054 				int			iz	= (int)(dz * (pRecord->asDouble(zField) - zMin));
1055 				wxColour	ic	= Get_Color_asWX(pColors->Get_Color(iz < 0 ? 0 : (iz >= 255 ? 255 : iz)));
1056 
1057 				if( !bOutline )
1058 				{
1059 					dc.SetPen(wxPen(ic));
1060 				}
1061 
1062 				dc.SetBrush(wxBrush(ic));
1063 
1064 				dc.DrawCircle(DRAW_GET_XPOS, DRAW_GET_YPOS, Size);
1065 			}
1066 		}
1067 	}
1068 }
1069 
1070 //---------------------------------------------------------
_Draw_Lines(wxDC & dc,wxRect r,double dx,double dy,int iField,double Offset,double Scale)1071 void CVIEW_Table_Diagram_Control::_Draw_Lines(wxDC &dc, wxRect r, double dx, double dy, int iField, double Offset, double Scale)
1072 {
1073 	if( m_pTable->Get_Count() > 1 )
1074 	{
1075 		iField	= m_Fields[iField];
1076 
1077 		int Size = m_Parameters("LINES_SIZE")->asInt();
1078 
1079 		dc.SetPen  (wxPen  (Get_Color_asWX(m_Colors.Get_Color(iField)), Size, wxPENSTYLE_SOLID));
1080 		dc.SetBrush(wxBrush(Get_Color_asWX(m_Colors.Get_Color(iField)), wxBRUSHSTYLE_SOLID));
1081 
1082 		for(int iRecord=0, bLast=0, xLast, yLast; iRecord<m_pTable->Get_Count(); iRecord++)
1083 		{
1084 			CSG_Table_Record	*pRecord	= m_pTable->Get_Record_byIndex(iRecord);
1085 
1086 			if( !pRecord->is_NoData(iField) && (m_pTable->Get_Selection_Count() < 1 || pRecord->is_Selected()) )
1087 			{
1088 				int	x	= DRAW_GET_XPOS;
1089 				int	y	= DRAW_GET_YPOS;
1090 
1091 				if( bLast )
1092 				{
1093 					dc.DrawLine(xLast, yLast, x, y);
1094 				}
1095 
1096 				xLast	= x;
1097 				yLast	= y;
1098 				bLast	= 1;
1099 			}
1100 			else
1101 			{
1102 				bLast	= 0;
1103 			}
1104 		}
1105 	}
1106 }
1107 
1108 //---------------------------------------------------------
_Draw_Bars(wxDC & dc,wxRect r,double dx,double dy,int iField,double Offset,double Scale)1109 void CVIEW_Table_Diagram_Control::_Draw_Bars(wxDC &dc, wxRect r, double dx, double dy, int iField, double Offset, double Scale)
1110 {
1111 	int	dxa	= m_xField < 0 ? (int)(dx / m_Fields.Get_Size() * iField) : iField + 0;
1112 	int	dxb	= m_xField < 0 ? (int)(dx / m_Fields.Get_Size()         ) : iField + 1;
1113 
1114 	int yOffset = r.GetBottom() - (int)(dy * (Offset - m_yMin));
1115 
1116 	iField	= m_Fields[iField];
1117 
1118 	dc.SetPen(wxPen(Get_Color_asWX(m_Colors.Get_Color(iField)), 1, wxPENSTYLE_SOLID));
1119 
1120 	for(int iRecord=0; iRecord<m_pTable->Get_Count(); iRecord++)
1121 	{
1122 		CSG_Table_Record	*pRecord	= m_pTable->Get_Record_byIndex(iRecord);
1123 
1124 		if( !pRecord->is_NoData(iField) && (m_pTable->Get_Selection_Count() < 1 || pRecord->is_Selected()) )
1125 		{
1126 			int	x	= DRAW_GET_XPOS + dxa;
1127 			int	y	= DRAW_GET_YPOS;
1128 
1129 			for(int xb=x+dxb; x<=xb; x++)
1130 			{
1131 				dc.DrawLine(x, yOffset, x, y);
1132 			}
1133 		}
1134 	}
1135 }
1136 
1137 
1138 ///////////////////////////////////////////////////////////
1139 //														 //
1140 //														 //
1141 //														 //
1142 ///////////////////////////////////////////////////////////
1143 
1144 //---------------------------------------------------------
1145 IMPLEMENT_CLASS(CVIEW_Table_Diagram, CVIEW_Base);
1146 
1147 //---------------------------------------------------------
BEGIN_EVENT_TABLE(CVIEW_Table_Diagram,CVIEW_Base)1148 BEGIN_EVENT_TABLE(CVIEW_Table_Diagram, CVIEW_Base)
1149 	EVT_SIZE    (CVIEW_Table_Diagram::On_Size)
1150 	EVT_KEY_DOWN(CVIEW_Table_Diagram::On_Key_Down)
1151 
1152 	EVT_MENU(ID_CMD_DIAGRAM_PARAMETERS  , CVIEW_Table_Diagram::On_Parameters)
1153 	EVT_MENU(ID_CMD_DIAGRAM_SIZE_FIT    , CVIEW_Table_Diagram::On_Size_Fit)
1154 	EVT_MENU(ID_CMD_DIAGRAM_SIZE_INC    , CVIEW_Table_Diagram::On_Size_Inc)
1155 	EVT_MENU(ID_CMD_DIAGRAM_SIZE_DEC    , CVIEW_Table_Diagram::On_Size_Dec)
1156 	EVT_MENU(ID_CMD_DIAGRAM_LEGEND      , CVIEW_Table_Diagram::On_Legend)
1157 	EVT_MENU(ID_CMD_DIAGRAM_TO_CLIPBOARD, CVIEW_Table_Diagram::On_SaveToClipboard)
1158 END_EVENT_TABLE()
1159 
1160 
1161 ///////////////////////////////////////////////////////////
1162 //														 //
1163 ///////////////////////////////////////////////////////////
1164 
1165 //---------------------------------------------------------
1166 CVIEW_Table_Diagram::CVIEW_Table_Diagram(CWKSP_Table *pTable)
1167 	: CVIEW_Base(pTable, ID_VIEW_TABLE_DIAGRAM, wxString::Format("%s [%s]", _TL("Diagram"), pTable->Get_Name().c_str()), ID_IMG_WND_DIAGRAM, false)
1168 {
1169 	SYS_Set_Color_BG_Window(this);
1170 
1171 	m_pControl	= new CVIEW_Table_Diagram_Control(this, pTable);
1172 
1173 	if( m_pControl->Set_Parameters() )
1174 	{
1175 		Do_Show();
1176 	}
1177 	else
1178 	{
1179 		Destroy();
1180 	}
1181 }
1182 
1183 
1184 ///////////////////////////////////////////////////////////
1185 //														 //
1186 ///////////////////////////////////////////////////////////
1187 
1188 //---------------------------------------------------------
_Create_Menu(void)1189 wxMenu * CVIEW_Table_Diagram::_Create_Menu(void)
1190 {
1191 	wxMenu	*pMenu	= new wxMenu;
1192 
1193 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_DIAGRAM_PARAMETERS);
1194 	pMenu->AppendSeparator();
1195 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_DIAGRAM_SIZE_FIT);
1196 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_DIAGRAM_SIZE_INC);
1197 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_DIAGRAM_SIZE_DEC);
1198 	CMD_Menu_Add_Item(pMenu,  true, ID_CMD_DIAGRAM_LEGEND);
1199 	pMenu->AppendSeparator();
1200 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_DIAGRAM_TO_CLIPBOARD);
1201 
1202 	return( pMenu );
1203 }
1204 
1205 //---------------------------------------------------------
_Create_ToolBar(void)1206 wxToolBarBase * CVIEW_Table_Diagram::_Create_ToolBar(void)
1207 {
1208 	wxToolBarBase	*pToolBar	= CMD_ToolBar_Create(ID_TB_VIEW_TABLE_DIAGRAM);
1209 
1210 	CMD_ToolBar_Add_Item(pToolBar, false, ID_CMD_DIAGRAM_PARAMETERS);
1211 	CMD_ToolBar_Add_Item(pToolBar, false, ID_CMD_DIAGRAM_SIZE_FIT);
1212 	CMD_ToolBar_Add_Item(pToolBar, false, ID_CMD_DIAGRAM_SIZE_INC);
1213 	CMD_ToolBar_Add_Item(pToolBar, false, ID_CMD_DIAGRAM_SIZE_DEC);
1214 
1215 	CMD_ToolBar_Add(pToolBar, _TL("Diagram"));
1216 
1217 	return( pToolBar );
1218 }
1219 
1220 
1221 ///////////////////////////////////////////////////////////
1222 //														 //
1223 ///////////////////////////////////////////////////////////
1224 
1225 //---------------------------------------------------------
Do_Update(void)1226 void CVIEW_Table_Diagram::Do_Update(void)
1227 {
1228 	m_pControl->Update_Diagram();
1229 }
1230 
1231 
1232 ///////////////////////////////////////////////////////////
1233 //														 //
1234 ///////////////////////////////////////////////////////////
1235 
1236 //---------------------------------------------------------
On_Size(wxSizeEvent & event)1237 void CVIEW_Table_Diagram::On_Size(wxSizeEvent &event)
1238 {
1239 	m_pControl->SetSize(GetClientSize());
1240 }
1241 
1242 //---------------------------------------------------------
On_Key_Down(wxKeyEvent & event)1243 void CVIEW_Table_Diagram::On_Key_Down(wxKeyEvent &event)
1244 {
1245 	m_pControl->On_Key_Down(event);
1246 }
1247 
1248 
1249 ///////////////////////////////////////////////////////////
1250 //														 //
1251 ///////////////////////////////////////////////////////////
1252 
1253 //---------------------------------------------------------
On_Parameters(wxCommandEvent & event)1254 void CVIEW_Table_Diagram::On_Parameters(wxCommandEvent &event)
1255 {
1256 	m_pControl->Set_Parameters();
1257 }
1258 
1259 //---------------------------------------------------------
On_Size_Fit(wxCommandEvent & event)1260 void CVIEW_Table_Diagram::On_Size_Fit(wxCommandEvent &event)
1261 {
1262 	m_pControl->Fit_Size();
1263 }
1264 
1265 //---------------------------------------------------------
On_Size_Inc(wxCommandEvent & event)1266 void CVIEW_Table_Diagram::On_Size_Inc(wxCommandEvent &event)
1267 {
1268 	m_pControl->Set_Zoom(1.2);
1269 }
1270 
1271 //---------------------------------------------------------
On_Size_Dec(wxCommandEvent & event)1272 void CVIEW_Table_Diagram::On_Size_Dec(wxCommandEvent &event)
1273 {
1274 	m_pControl->Set_Zoom(1. / 1.2);
1275 }
1276 
1277 //---------------------------------------------------------
On_Legend(wxCommandEvent & event)1278 void CVIEW_Table_Diagram::On_Legend(wxCommandEvent &event)
1279 {
1280 	m_pControl->m_Parameters("LEGEND")->Set_Value(!m_pControl->m_Parameters("LEGEND")->asBool());
1281 
1282 	m_pControl->Refresh();
1283 }
1284 
1285 //---------------------------------------------------------
On_SaveToClipboard(wxCommandEvent & event)1286 void CVIEW_Table_Diagram::On_SaveToClipboard(wxCommandEvent &event)
1287 {
1288 	m_pControl->SaveToClipboard();
1289 }
1290 
1291 //---------------------------------------------------------
On_Command_UI(wxUpdateUIEvent & event)1292 void CVIEW_Table_Diagram::On_Command_UI(wxUpdateUIEvent &event)
1293 {
1294 	switch( event.GetId() )
1295 	{
1296 	case ID_CMD_DIAGRAM_LEGEND:
1297 		event.Check(m_pControl->m_Parameters("LEGEND")->asBool());
1298 		break;
1299 
1300 	//-----------------------------------------------------
1301 	default:
1302 		break;
1303 	}
1304 }
1305 
1306 
1307 ///////////////////////////////////////////////////////////
1308 //														 //
1309 //														 //
1310 //														 //
1311 ///////////////////////////////////////////////////////////
1312 
1313 //---------------------------------------------------------
1314