1
2 ///////////////////////////////////////////////////////////
3 // //
4 // SAGA //
5 // //
6 // System for Automated Geoscientific Analyses //
7 // //
8 // Application Programming Interface //
9 // //
10 // Library: SAGA_API //
11 // //
12 //-------------------------------------------------------//
13 // //
14 // tool.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'. //
22 // //
23 // This library is free software; you can redistribute //
24 // it and/or modify it under the terms of the GNU Lesser //
25 // General Public License as published by the Free //
26 // Software Foundation, either version 2.1 of the //
27 // License, or (at your option) any later version. //
28 // //
29 // This library is distributed in the hope that it will //
30 // be useful, but WITHOUT ANY WARRANTY; without even the //
31 // implied warranty of MERCHANTABILITY or FITNESS FOR A //
32 // PARTICULAR PURPOSE. See the GNU Lesser General Public //
33 // License for more details. //
34 // //
35 // You should have received a copy of the GNU Lesser //
36 // General Public License along with this program; if //
37 // not, see <http://www.gnu.org/licenses/>. //
38 // //
39 //-------------------------------------------------------//
40 // //
41 // contact: Olaf Conrad //
42 // Institute of Geography //
43 // University of Goettingen //
44 // Germany //
45 // //
46 // e-mail: oconrad@saga-gis.org //
47 // //
48 ///////////////////////////////////////////////////////////
49
50 //---------------------------------------------------------
51 #include "saga_api.h"
52 #include "data_manager.h"
53 #include "tool.h"
54 #include "tool_chain.h"
55
56 #include <wx/string.h>
57
58
59 ///////////////////////////////////////////////////////////
60 // //
61 // //
62 // //
63 ///////////////////////////////////////////////////////////
64
65 //---------------------------------------------------------
66 #define ADD_MESSAGE_EXECUTION(Text, Style) { SG_UI_Msg_Add(Text, true, Style); if( has_GUI() ) { SG_UI_Msg_Add_Execution(Text, true, Style); } }
67
68
69 ///////////////////////////////////////////////////////////
70 // //
71 // //
72 // //
73 ///////////////////////////////////////////////////////////
74
75 //---------------------------------------------------------
CSG_Tool(void)76 CSG_Tool::CSG_Tool(void)
77 {
78 m_ID = "-1";
79 m_Version = "1.0";
80
81 m_bError_Ignore = false;
82 m_bExecutes = false;
83 m_bWithGUI = true;
84
85 m_pParameters = NULL;
86 m_npParameters = 0;
87
88 Parameters.Create(this, SG_T("Tool"));
89 Parameters.Set_Callback_On_Parameter_Changed(&_On_Parameter_Changed);
90 Parameters.m_pTool = this;
91
92 Set_Show_Progress(true);
93 }
94
95 //---------------------------------------------------------
~CSG_Tool(void)96 CSG_Tool::~CSG_Tool(void)
97 {
98 if( m_Settings_Stack.Get_Size() > 0 )
99 {
100 for(size_t i=0; i<m_Settings_Stack.Get_Size(); i++)
101 {
102 delete(((CSG_Parameters **)m_Settings_Stack.Get_Array())[i]);
103 }
104 }
105
106 if( m_pParameters )
107 {
108 for(int i=0; i<m_npParameters; i++)
109 {
110 delete(m_pParameters[i]);
111 }
112
113 SG_Free(m_pParameters);
114 }
115
116 Destroy();
117 }
118
119
120 ///////////////////////////////////////////////////////////
121 // //
122 ///////////////////////////////////////////////////////////
123
124 //---------------------------------------------------------
Destroy(void)125 void CSG_Tool::Destroy(void)
126 {
127 m_bError_Ignore = false;
128
129 History_Supplement.Destroy();
130 }
131
132
133 ///////////////////////////////////////////////////////////
134 // //
135 ///////////////////////////////////////////////////////////
136
137 //---------------------------------------------------------
Get_Library(void) const138 const CSG_String & CSG_Tool::Get_Library(void) const
139 {
140 return( m_Library );
141 }
142
143 //---------------------------------------------------------
Get_File_Name(void) const144 const CSG_String & CSG_Tool::Get_File_Name(void) const
145 {
146 return( m_File_Name );
147 }
148
149 //---------------------------------------------------------
Set_Name(const CSG_String & String)150 void CSG_Tool::Set_Name(const CSG_String &String)
151 {
152 Parameters.Set_Name(String);
153 }
154
Get_Name(void) const155 const CSG_String & CSG_Tool::Get_Name(void) const
156 {
157 return( Parameters.Get_Name() );
158 }
159
160 //---------------------------------------------------------
Set_Author(const CSG_String & String)161 void CSG_Tool::Set_Author(const CSG_String &String)
162 {
163 m_Author = String;
164 }
165
Get_Author(void) const166 const CSG_String & CSG_Tool::Get_Author(void) const
167 {
168 return( m_Author );
169 }
170
171 //---------------------------------------------------------
Set_Version(const CSG_String & String)172 void CSG_Tool::Set_Version(const CSG_String &String)
173 {
174 m_Version = String;
175 }
176
Get_Version(void) const177 const CSG_String & CSG_Tool::Get_Version(void) const
178 {
179 return( m_Version );
180 }
181
182 //---------------------------------------------------------
Set_Description(const CSG_String & String)183 void CSG_Tool::Set_Description(const CSG_String &String)
184 {
185 Parameters.Set_Description(String);
186 }
187
Get_Description(void) const188 const CSG_String & CSG_Tool::Get_Description(void) const
189 {
190 return( Parameters.Get_Description().is_Empty() ? Get_Name() : Parameters.Get_Description() );
191 }
192
193 //---------------------------------------------------------
Add_Reference(const CSG_String & Authors,const CSG_String & Year,const CSG_String & Title,const CSG_String & Where,const SG_Char * Link,const SG_Char * Link_Text)194 void CSG_Tool::Add_Reference(const CSG_String &Authors, const CSG_String &Year, const CSG_String &Title, const CSG_String &Where, const SG_Char *Link, const SG_Char *Link_Text)
195 {
196 Parameters.Add_Reference(Authors, Year, Title, Where, Link, Link_Text);
197 }
198
Add_Reference(const CSG_String & Link,const SG_Char * Link_Text)199 void CSG_Tool::Add_Reference(const CSG_String &Link, const SG_Char *Link_Text)
200 {
201 Parameters.Add_Reference(Link, Link_Text);
202 }
203
Get_References(void) const204 const CSG_Strings & CSG_Tool::Get_References(void) const
205 {
206 return( Parameters.Get_References() );
207 }
208
209 //---------------------------------------------------------
Get_MenuPath(bool bSolved)210 CSG_String CSG_Tool::Get_MenuPath(bool bSolved)
211 {
212 if( !bSolved )
213 {
214 return( Get_MenuPath() );
215 }
216
217 CSG_String Menu = Get_MenuPath();
218
219 if( Menu.Length() > 1 && Menu[1] == ':' )
220 {
221 if( Menu[0] == 'A' || Menu[0] == 'a' ) // absolute menu path, overwrites library's default menu path
222 {
223 return( Menu.AfterFirst(':') );
224 }
225
226 Menu = Menu.AfterFirst(':'); // Menu[0] == 'R' || Menu[0] == 'r' // menu path explicitly declared as relative to library's default menu path
227 }
228
229 if( m_Library_Menu.is_Empty() )
230 {
231 return( Menu );
232 }
233
234 if( Menu.is_Empty() )
235 {
236 return( m_Library_Menu );
237 }
238
239 return( m_Library_Menu + "|" + Menu );
240 }
241
242 //---------------------------------------------------------
has_GUI(void) const243 bool CSG_Tool::has_GUI(void) const
244 {
245 return( m_bWithGUI && SG_UI_Get_Window_Main() != NULL );
246 }
247
248
249 ///////////////////////////////////////////////////////////
250 // //
251 // //
252 // //
253 ///////////////////////////////////////////////////////////
254
255 //---------------------------------------------------------
Execute(bool bAddHistory)256 bool CSG_Tool::Execute(bool bAddHistory)
257 {
258 if( m_bExecutes )
259 {
260 return( false );
261 }
262
263 m_bExecutes = true;
264
265 m_bError_Ignore = false;
266
267 bool bResult = false;
268
269 m_Execution_Info.Clear();
270
271 History_Supplement.Destroy();
272
273 //-----------------------------------------------------
274 if( Parameters.Get_Manager() == &SG_Get_Data_Manager() )
275 {
276 ADD_MESSAGE_EXECUTION(CSG_String::Format("[%s] %s...", Get_Name().c_str(), _TL("Execution started")), SG_UI_MSG_STYLE_SUCCESS);
277 }
278
279 Update_Parameter_States();
280
281 if( Parameters.DataObjects_Create() == false )
282 {
283 Message_Dlg(_TL("could not initialize data objects"));
284
285 _Synchronize_DataObjects(); // not all, but some objects might have been created!
286 }
287 else
288 {
289 Parameters.Msg_String(false);
290
291 ///////////////////////////////////////////////////////////
292 #if !defined(_DEBUG) && !defined(_OPENMP) && defined(_SAGA_MSW)
293 #define _TOOL_EXCEPTION
294 __try
295 {
296 #endif
297 ///////////////////////////////////////////////////////////
298
299 CSG_DateTime Started(CSG_DateTime::Now());
300 bResult = On_Execute();
301 CSG_TimeSpan Span = CSG_DateTime::Now() - Started;
302
303 ///////////////////////////////////////////////////////////
304 #ifdef _TOOL_EXCEPTION
305 } // try
306 __except(1)
307 {
308 Message_Dlg("Tool caused access violation!");
309 } // except(1)
310 #endif
311 ///////////////////////////////////////////////////////////
312
313 _Synchronize_DataObjects();
314
315 if( !Process_Get_Okay(false) )
316 {
317 SG_UI_Msg_Add(_TL("Execution has been stopped by user!"), true, SG_UI_MSG_STYLE_BOLD);
318
319 bResult = false;
320 }
321
322 if( bResult && bAddHistory )
323 {
324 _Set_Output_History();
325 }
326
327 //-------------------------------------------------
328 if( is_Interactive() )
329 {
330 if( bResult )
331 {
332 CSG_String Text(CSG_String::Format("\n%s...", _TL("Interactive tool started and is waiting for user input.")));
333
334 SG_UI_Msg_Add (Text, false, SG_UI_MSG_STYLE_BOLD);
335 SG_UI_Msg_Add_Execution(Text, false, SG_UI_MSG_STYLE_BOLD);
336 }
337 else
338 {
339 ADD_MESSAGE_EXECUTION(_TL("Interactive tool initialization failed."), SG_UI_MSG_STYLE_FAILURE);
340 }
341 }
342 else
343 {
344 CSG_String Time =
345 Span.Get_Hours () >= 1 ? (Span.Format("%Hh %Mm %Ss"))
346 : Span.Get_Minutes () >= 1 ? (Span.Format( "%Mm %Ss"))
347 : Span.Get_Seconds () >= 1 ? (Span.Format( "%Ss"))
348 : Span.Get_Milliseconds() >= 1 ? (Span.Format("%l ") + _TL("milliseconds"))
349 : CSG_String(_TL("less than 1 millisecond"));
350
351 if( Parameters.Get_Manager() != &SG_Get_Data_Manager() )
352 {
353 SG_UI_Msg_Add_Execution(CSG_String::Format("\n[%s] %s: %s", Get_Name().c_str(),
354 _TL("execution time"), Time.c_str()),
355 false, SG_UI_MSG_STYLE_NORMAL
356 );
357 }
358 else
359 {
360 SG_UI_Msg_Add_Execution(CSG_String::Format("\n__________\n%s %s: %ld %s (%s)\n", _TL("total"),
361 _TL("execution time"), Span.Get_Milliseconds(), _TL("milliseconds"), Time.c_str()),
362 false, SG_UI_MSG_STYLE_BOLD
363 );
364
365 ADD_MESSAGE_EXECUTION(CSG_String::Format("[%s] %s (%s)", Get_Name().c_str(),
366 bResult ? _TL("Execution succeeded") : _TL("Execution failed"), Time.c_str()),
367 bResult ? SG_UI_MSG_STYLE_SUCCESS : SG_UI_MSG_STYLE_FAILURE
368 );
369 }
370 }
371 }
372
373 //-----------------------------------------------------
374 History_Supplement.Destroy();
375
376 m_bExecutes = false;
377
378 SG_UI_Process_Set_Okay ();
379 SG_UI_Process_Set_Ready();
380
381 return( bResult );
382 }
383
384
385 ///////////////////////////////////////////////////////////
386 // //
387 // //
388 // //
389 ///////////////////////////////////////////////////////////
390
391 //---------------------------------------------------------
_Synchronize_DataObjects(void)392 bool CSG_Tool::_Synchronize_DataObjects(void)
393 {
394 Parameters.DataObjects_Synchronize();
395
396 for(int i=0; i<m_npParameters; i++)
397 {
398 m_pParameters[i]->DataObjects_Synchronize();
399 }
400
401 CSG_Projection Projection;
402
403 if( do_Sync_Projections() && Get_Projection(Projection) )
404 {
405 Parameters.DataObjects_Set_Projection(Projection);
406
407 for(int j=0; j<m_npParameters; j++)
408 {
409 m_pParameters[j]->DataObjects_Set_Projection(Projection);
410 }
411
412 return( true );
413 }
414
415 return( false );
416 }
417
418 //---------------------------------------------------------
Get_Projection(CSG_Projection & Projection) const419 bool CSG_Tool::Get_Projection(CSG_Projection &Projection) const
420 {
421 Projection.Destroy();
422
423 Parameters.DataObjects_Get_Projection(Projection);
424
425 for(int i=0; i<m_npParameters && !Projection.is_Okay(); i++)
426 {
427 m_pParameters[i]->DataObjects_Get_Projection(Projection);
428 }
429
430 return( Projection.is_Okay() );
431 }
432
433
434 ///////////////////////////////////////////////////////////
435 // //
436 // Parameters //
437 // //
438 ///////////////////////////////////////////////////////////
439
440 //---------------------------------------------------------
_On_Parameter_Changed(CSG_Parameter * pParameter,int Flags)441 int CSG_Tool::_On_Parameter_Changed(CSG_Parameter *pParameter, int Flags)
442 {
443 CSG_Parameters *pParameters = pParameter ? pParameter ->Get_Parameters() : NULL;
444 CSG_Tool *pTool = pParameters ? pParameters->Get_Tool () : NULL;
445
446 if( pTool )
447 {
448 if( Flags & PARAMETER_CHECK_VALUES )
449 {
450 pTool->On_Parameter_Changed(pParameters, pParameter);
451 }
452
453 if( Flags & PARAMETER_CHECK_ENABLE )
454 {
455 pTool->On_Parameters_Enable(pParameters, pParameter);
456 }
457
458 return( 1 );
459 }
460
461 return( 0 );
462 }
463
464 //---------------------------------------------------------
On_Parameter_Changed(CSG_Parameters * pParameters,CSG_Parameter * pParameter)465 int CSG_Tool::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
466 {
467 return( 1 );
468 }
469
470 //---------------------------------------------------------
On_Parameters_Enable(CSG_Parameters * pParameters,CSG_Parameter * pParameter)471 int CSG_Tool::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
472 {
473 return( 1 );
474 }
475
476
477 ///////////////////////////////////////////////////////////
478 // //
479 // Extra Parameters //
480 // //
481 ///////////////////////////////////////////////////////////
482
483 //---------------------------------------------------------
Add_Parameters(const CSG_String & Identifier,const CSG_String & Name,const CSG_String & Description)484 CSG_Parameters * CSG_Tool::Add_Parameters(const CSG_String &Identifier, const CSG_String &Name, const CSG_String &Description)
485 {
486 CSG_Parameters *pParameters;
487
488 m_pParameters = (CSG_Parameters **)SG_Realloc(m_pParameters, (m_npParameters + 1) * sizeof(CSG_Parameters *));
489 pParameters = m_pParameters[m_npParameters++] = new CSG_Parameters();
490
491 pParameters->Create(this, Name, Description, Identifier);
492 pParameters->Set_Callback_On_Parameter_Changed(&_On_Parameter_Changed);
493 pParameters->m_pTool = this;
494
495 return( pParameters );
496 }
497
498 //---------------------------------------------------------
Get_Parameters(const CSG_String & Identifier)499 CSG_Parameters * CSG_Tool::Get_Parameters(const CSG_String &Identifier)
500 {
501 for(int i=0; i<m_npParameters; i++)
502 {
503 if( m_pParameters[i]->Cmp_Identifier(Identifier) )
504 {
505 return( m_pParameters[i] );
506 }
507 }
508
509 return( NULL );
510 }
511
512 //---------------------------------------------------------
Dlg_Parameters(const CSG_String & Identifier)513 bool CSG_Tool::Dlg_Parameters(const CSG_String &Identifier)
514 {
515 CSG_Parameters *pParameters = Get_Parameters(Identifier);
516
517 if( pParameters && (!pParameters->is_Managed() || Dlg_Parameters(pParameters, Get_Name())) )
518 {
519 pParameters->Set_History(History_Supplement);
520
521 return( true );
522 }
523
524 return( false );
525 }
526
527 //---------------------------------------------------------
Dlg_Parameters(CSG_Parameters * pParameters,const CSG_String & Caption)528 bool CSG_Tool::Dlg_Parameters(CSG_Parameters *pParameters, const CSG_String &Caption)
529 {
530 return( pParameters ? SG_UI_Dlg_Parameters(pParameters, Caption) : false );
531 }
532
533
534 ///////////////////////////////////////////////////////////
535 // //
536 ///////////////////////////////////////////////////////////
537
538 //---------------------------------------------------------
Set_Callback(bool bActive)539 void CSG_Tool::Set_Callback(bool bActive)
540 {
541 Parameters.Set_Callback(bActive);
542
543 for(int i=0; i<m_npParameters; i++)
544 {
545 m_pParameters[i]->Set_Callback(bActive);
546 }
547 }
548
549 //---------------------------------------------------------
Set_Manager(class CSG_Data_Manager * pManager)550 bool CSG_Tool::Set_Manager(class CSG_Data_Manager *pManager)
551 {
552 Parameters.Set_Manager(pManager);
553
554 for(int i=0; i<m_npParameters; i++)
555 {
556 m_pParameters[i]->Set_Manager(pManager);
557 }
558
559 return( true );
560 }
561
562
563 ///////////////////////////////////////////////////////////
564 // //
565 // //
566 // //
567 ///////////////////////////////////////////////////////////
568
569 //---------------------------------------------------------
Settings_Push(CSG_Data_Manager * pManager)570 bool CSG_Tool::Settings_Push(CSG_Data_Manager *pManager)
571 {
572 if( m_Settings_Stack.Get_Value_Size() != sizeof(CSG_Parameters *) )
573 {
574 m_Settings_Stack.Create(sizeof(CSG_Parameters *));
575 }
576
577 size_t n = m_Settings_Stack.Get_Size();
578
579 CSG_Parameters **pP = (CSG_Parameters **)m_Settings_Stack.Get_Array(n + 1 + m_npParameters);
580
581 if( pP )
582 {
583 pP[n++] = new CSG_Parameters(Parameters); Parameters.Restore_Defaults(true); Parameters.Set_Manager(pManager);
584
585 for(int i=0; i<m_npParameters; i++)
586 {
587 pP[n++] = new CSG_Parameters(*m_pParameters[i]); m_pParameters[i]->Restore_Defaults(true); m_pParameters[i]->Set_Manager(pManager);
588 }
589
590 return( true );
591 }
592
593 return( false );
594 }
595
596 //---------------------------------------------------------
Settings_Pop(void)597 bool CSG_Tool::Settings_Pop(void)
598 {
599 CSG_Parameters **pP = (CSG_Parameters **)m_Settings_Stack.Get_Array();
600
601 if( pP && (int)m_Settings_Stack.Get_Size() >= 1 + m_npParameters )
602 {
603 size_t n = m_Settings_Stack.Get_Size() - 1;
604
605 for(int i=m_npParameters-1; i>=0; i--, n--)
606 {
607 m_pParameters[i]->Assign_Values(pP[n]); m_pParameters[i]->Set_Manager(pP[n]->Get_Manager()); delete(pP[n]);
608 }
609
610 Parameters.Assign_Values(pP[n]); Parameters.Set_Manager(pP[n]->Get_Manager()); delete(pP[n]);
611
612 m_Settings_Stack.Set_Array(n);
613
614 return( true );
615 }
616
617 return( false );
618 }
619
620
621 ///////////////////////////////////////////////////////////
622 // //
623 // Progress //
624 // //
625 ///////////////////////////////////////////////////////////
626
627 //---------------------------------------------------------
Set_Show_Progress(bool bOn)628 void CSG_Tool::Set_Show_Progress(bool bOn)
629 {
630 m_bShow_Progress = bOn;
631 }
632
633 //---------------------------------------------------------
Set_Progress(double Percent) const634 bool CSG_Tool::Set_Progress(double Percent) const
635 {
636 return( Set_Progress(Percent, 100.0) );
637 }
638
639 //---------------------------------------------------------
Set_Progress(double Position,double Range) const640 bool CSG_Tool::Set_Progress(double Position, double Range) const
641 {
642 return( m_bShow_Progress ? SG_UI_Process_Set_Progress(Position, Range) : Process_Get_Okay(false) );
643 }
644
645 //---------------------------------------------------------
Stop_Execution(bool bDialog)646 bool CSG_Tool::Stop_Execution(bool bDialog)
647 {
648 m_bExecutes = false;
649
650 return( SG_UI_Stop_Execution(bDialog) );
651 }
652
653
654 ///////////////////////////////////////////////////////////
655 // //
656 // Message //
657 // //
658 ///////////////////////////////////////////////////////////
659
660 //---------------------------------------------------------
Message_Dlg(const CSG_String & Text,const SG_Char * Caption)661 void CSG_Tool::Message_Dlg(const CSG_String &Text, const SG_Char *Caption)
662 {
663 SG_UI_Dlg_Message(Text, Caption && Caption[0] != '\0' ? Caption : Get_Name().c_str());
664 }
665
666 //---------------------------------------------------------
Message_Dlg_Confirm(const CSG_String & Text,const SG_Char * Caption)667 bool CSG_Tool::Message_Dlg_Confirm(const CSG_String &Text, const SG_Char *Caption)
668 {
669 return( SG_UI_Dlg_Continue(Text, Caption && Caption[0] != '\0' ? Caption : Get_Name().c_str()) );
670 }
671
672 //---------------------------------------------------------
Error_Set(TSG_Tool_Error Error_ID)673 bool CSG_Tool::Error_Set(TSG_Tool_Error Error_ID)
674 {
675 switch( Error_ID )
676 {
677 default:
678 return( Error_Set(_TL("Unknown Error")) );
679
680 case TOOL_ERROR_Calculation:
681 return( Error_Set(_TL("Calculation Error")) );
682 }
683 }
684
685 //---------------------------------------------------------
Error_Set(const CSG_String & Text)686 bool CSG_Tool::Error_Set(const CSG_String &Text)
687 {
688 SG_UI_Msg_Add_Error(Text);
689
690 m_Execution_Info += "\n____\n" + Text;
691
692 if( SG_UI_Process_Get_Okay(false) && !m_bError_Ignore )
693 {
694 switch( SG_UI_Dlg_Error(Text, CSG_String::Format("%s: %s?", _TL("Error"), _TL("Ignore"))) )
695 {
696 default:
697 SG_UI_Process_Set_Okay(false);
698 break;
699
700 case 1:
701 m_bError_Ignore = true;
702 break;
703 }
704 }
705
706 return( SG_UI_Process_Get_Okay(false) );
707 }
708
709 //---------------------------------------------------------
Error_Fmt(const char * Format,...)710 bool CSG_Tool::Error_Fmt(const char *Format, ...)
711 {
712 wxString _s;
713
714 va_list argptr;
715
716 #ifdef _SAGA_LINUX
717 // workaround as we only use wide characters
718 // since wx 2.9.4 so interpret strings as multibyte
719 wxString _Format(Format); _Format.Replace("%s", "%ls");
720 va_start(argptr, _Format);
721 _s.PrintfV(_Format, argptr);
722 #else
723 va_start(argptr, Format);
724 _s.PrintfV(Format, argptr);
725 #endif
726
727 va_end(argptr);
728
729 CSG_String s(&_s);
730
731 return( Error_Set(s) );
732 }
733
734 //---------------------------------------------------------
Error_Fmt(const wchar_t * Format,...)735 bool CSG_Tool::Error_Fmt(const wchar_t *Format, ...)
736 {
737 wxString _s;
738
739 va_list argptr;
740
741 #ifdef _SAGA_LINUX
742 // workaround as we only use wide characters
743 // since wx 2.9.4 so interpret strings as multibyte
744 wxString _Format(Format); _Format.Replace("%s", "%ls");
745 va_start(argptr, _Format);
746 _s.PrintfV(_Format, argptr);
747 #else
748 va_start(argptr, Format);
749 _s.PrintfV(Format, argptr);
750 #endif
751
752 va_end(argptr);
753
754 CSG_String s(&_s);
755
756 return( Error_Set(s) );
757 }
758
759
760 ///////////////////////////////////////////////////////////
761 // //
762 // DataObjects / GUI Interaction //
763 // //
764 ///////////////////////////////////////////////////////////
765
766 //---------------------------------------------------------
DataObject_Add(CSG_Data_Object * pDataObject,bool bUpdate)767 bool CSG_Tool::DataObject_Add(CSG_Data_Object *pDataObject, bool bUpdate)
768 {
769 if( Parameters.Get_Manager() )
770 {
771 Parameters.Get_Manager()->Add(pDataObject);
772 }
773
774 if( Parameters.Get_Manager() == &SG_Get_Data_Manager() ) // prevent that local data manager send their data objects to gui
775 {
776 return( SG_UI_DataObject_Add(pDataObject, bUpdate) );
777 }
778
779 return( true );
780 }
781
782 //---------------------------------------------------------
DataObject_Update_All(void)783 void CSG_Tool::DataObject_Update_All(void)
784 {
785 for(int i=0; i<Parameters.Get_Count(); i++)
786 {
787 if( Parameters(i)->is_Output() )
788 {
789 if( Parameters(i)->is_DataObject() )
790 {
791 DataObject_Update(Parameters(i)->asDataObject(), false);
792 }
793 else if( Parameters(i)->is_DataObject_List() )
794 {
795 for(int j=0; j<Parameters(i)->asList()->Get_Item_Count(); j++)
796 {
797 DataObject_Update(Parameters(i)->asList()->Get_Item(j), false);
798 }
799 }
800 }
801 }
802 }
803
804
805 ///////////////////////////////////////////////////////////
806 // //
807 // Static Data Message/Progress Functions //
808 // //
809 ///////////////////////////////////////////////////////////
810
811 //---------------------------------------------------------
Process_Get_Okay(bool bBlink)812 bool CSG_Tool::Process_Get_Okay(bool bBlink)
813 {
814 return( SG_UI_Process_Get_Okay(bBlink) );
815 }
816
817 //---------------------------------------------------------
Process_Set_Text(const CSG_String & Text)818 void CSG_Tool::Process_Set_Text(const CSG_String &Text)
819 {
820 SG_UI_Process_Set_Text(Text);
821 }
822
823 //---------------------------------------------------------
Process_Set_Text(const char * Format,...)824 void CSG_Tool::Process_Set_Text(const char *Format, ...)
825 {
826 wxString _s;
827
828 va_list argptr;
829
830 #ifdef _SAGA_LINUX
831 // workaround as we only use wide characters
832 // since wx 2.9.4 so interpret strings as multibyte
833 wxString _Format(Format); _Format.Replace("%s", "%ls");
834 va_start(argptr, _Format);
835 _s.PrintfV(_Format, argptr);
836 #else
837 va_start(argptr, Format);
838 _s.PrintfV(Format, argptr);
839 #endif
840
841 va_end(argptr);
842
843 CSG_String s(&_s);
844
845 SG_UI_Process_Set_Text(s);
846 }
847
848 //---------------------------------------------------------
Process_Set_Text(const wchar_t * Format,...)849 void CSG_Tool::Process_Set_Text(const wchar_t *Format, ...)
850 {
851 wxString _s;
852
853 va_list argptr;
854
855 #ifdef _SAGA_LINUX
856 // workaround as we only use wide characters
857 // since wx 2.9.4 so interpret strings as multibyte
858 wxString _Format(Format); _Format.Replace("%s", "%ls");
859 va_start(argptr, _Format);
860 _s.PrintfV(_Format, argptr);
861 #else
862 va_start(argptr, Format);
863 _s.PrintfV(Format, argptr);
864 #endif
865
866 va_end(argptr);
867
868 CSG_String s(&_s);
869
870 SG_UI_Process_Set_Text(s);
871 }
872
873 //---------------------------------------------------------
Message_Add(const CSG_String & Text,bool bNewLine)874 void CSG_Tool::Message_Add(const CSG_String &Text, bool bNewLine)
875 {
876 SG_UI_Msg_Add_Execution(Text, bNewLine);
877
878 if( bNewLine )
879 {
880 m_Execution_Info += "\n";
881 }
882
883 m_Execution_Info += Text;
884 }
885
886 //---------------------------------------------------------
Message_Fmt(const char * Format,...)887 void CSG_Tool::Message_Fmt(const char *Format, ...)
888 {
889 wxString _s;
890
891 va_list argptr;
892
893 #ifdef _SAGA_LINUX
894 // workaround as we only use wide characters
895 // since wx 2.9.4 so interpret strings as multibyte
896 wxString _Format(Format); _Format.Replace("%s", "%ls");
897 va_start(argptr, _Format);
898 _s.PrintfV(_Format, argptr);
899 #else
900 va_start(argptr, Format);
901 _s.PrintfV(Format, argptr);
902 #endif
903
904 va_end(argptr);
905
906 CSG_String s(&_s);
907
908 Message_Add(s, false);
909 }
910
911 //---------------------------------------------------------
Message_Fmt(const wchar_t * Format,...)912 void CSG_Tool::Message_Fmt(const wchar_t *Format, ...)
913 {
914 wxString _s;
915
916 va_list argptr;
917
918 #ifdef _SAGA_LINUX
919 // workaround as we only use wide characters
920 // since wx 2.9.4 so interpret strings as multibyte
921 wxString _Format(Format); _Format.Replace("%s", "%ls");
922 va_start(argptr, _Format);
923 _s.PrintfV(_Format, argptr);
924 #else
925 va_start(argptr, Format);
926 _s.PrintfV(Format, argptr);
927 #endif
928
929 va_end(argptr);
930
931 CSG_String s(&_s);
932
933 Message_Add(s, false);
934 }
935
936
937 ///////////////////////////////////////////////////////////
938 // //
939 // Static Data Object Property Functions //
940 // //
941 ///////////////////////////////////////////////////////////
942
943 //---------------------------------------------------------
DataObject_Update(CSG_Data_Object * pDataObject,int Show)944 bool CSG_Tool::DataObject_Update(CSG_Data_Object *pDataObject, int Show)
945 {
946 return( SG_UI_DataObject_Update(pDataObject, Show, NULL) );
947 }
948
DataObject_Update(CSG_Data_Object * pDataObject,double Minimum,double Maximum,int Show)949 bool CSG_Tool::DataObject_Update(CSG_Data_Object *pDataObject, double Minimum, double Maximum, int Show)
950 {
951 CSG_Parameters P;
952
953 return( DataObject_Get_Parameters(pDataObject, P)
954 && P.Set_Parameter("STRETCH_UPDATE" , false ) // internal update flag
955 && P.Set_Parameter("STRETCH_DEFAULT" , 3 ) // manual
956 && P.Set_Parameter("METRIC_ZRANGE.MIN", Minimum)
957 && P.Set_Parameter("METRIC_ZRANGE.MAX", Maximum)
958 && SG_UI_DataObject_Update(pDataObject, Show, &P)
959 );
960 }
961
962 //---------------------------------------------------------
DataObject_Get_Colors(CSG_Data_Object * pDataObject,CSG_Colors & Colors)963 bool CSG_Tool::DataObject_Get_Colors(CSG_Data_Object *pDataObject, CSG_Colors &Colors)
964 {
965 return( SG_UI_DataObject_Colors_Get(pDataObject, &Colors) );
966 }
967
DataObject_Set_Colors(CSG_Data_Object * pDataObject,const CSG_Colors & Colors)968 bool CSG_Tool::DataObject_Set_Colors(CSG_Data_Object *pDataObject, const CSG_Colors &Colors)
969 {
970 CSG_Colors c(Colors);
971
972 return( SG_UI_DataObject_Colors_Set(pDataObject, &c) );
973 }
974
DataObject_Set_Colors(CSG_Data_Object * pDataObject,int nColors,int Palette,bool bRevert)975 bool CSG_Tool::DataObject_Set_Colors(CSG_Data_Object *pDataObject, int nColors, int Palette, bool bRevert)
976 {
977 CSG_Colors c(nColors, Palette, bRevert);
978
979 return( SG_UI_DataObject_Colors_Set(pDataObject, &c) );
980 }
981
982 //---------------------------------------------------------
DataObject_Get_Parameters(CSG_Data_Object * pDataObject,CSG_Parameters & Parameters)983 bool CSG_Tool::DataObject_Get_Parameters(CSG_Data_Object *pDataObject, CSG_Parameters &Parameters)
984 {
985 return( SG_UI_DataObject_Params_Get(pDataObject, &Parameters) );
986 }
987
DataObject_Set_Parameters(CSG_Data_Object * pDataObject,CSG_Parameters & Parameters)988 bool CSG_Tool::DataObject_Set_Parameters(CSG_Data_Object *pDataObject, CSG_Parameters &Parameters)
989 {
990 return( SG_UI_DataObject_Params_Set(pDataObject, &Parameters) );
991 }
992
DataObject_Set_Parameters(CSG_Data_Object * pDataObject,CSG_Data_Object * pCopy)993 bool CSG_Tool::DataObject_Set_Parameters(CSG_Data_Object *pDataObject, CSG_Data_Object *pCopy)
994 {
995 if( pDataObject == pCopy )
996 {
997 return( true );
998 }
999
1000 CSG_Parameters P;
1001
1002 if( DataObject_Get_Parameters(pCopy, P) )
1003 {
1004 P.Del_Parameter("OBJECT_NODATA" );
1005 P.Del_Parameter("OBJECT_Z_FACTOR");
1006 P.Del_Parameter("OBJECT_Z_OFFSET");
1007
1008 return( DataObject_Set_Parameters(pDataObject, P) );
1009 }
1010
1011 return( false );
1012 }
1013
1014 //---------------------------------------------------------
DataObject_Get_Parameter(CSG_Data_Object * pDataObject,const CSG_String & ID)1015 CSG_Parameter * CSG_Tool::DataObject_Get_Parameter(CSG_Data_Object *pDataObject, const CSG_String &ID)
1016 {
1017 static CSG_Parameters P;
1018
1019 return( DataObject_Get_Parameters(pDataObject, P) ? P(ID) : NULL );
1020 }
1021
DataObject_Set_Parameter(CSG_Data_Object * pDataObject,CSG_Parameter * pParameter)1022 bool CSG_Tool::DataObject_Set_Parameter(CSG_Data_Object *pDataObject, CSG_Parameter *pParameter)
1023 {
1024 CSG_Parameters P;
1025
1026 return( P._Add(pParameter) != NULL && DataObject_Set_Parameters(pDataObject, P) );
1027 }
1028
DataObject_Set_Parameter(CSG_Data_Object * pDataObject,CSG_Data_Object * pCopy,const CSG_String & ID)1029 bool CSG_Tool::DataObject_Set_Parameter(CSG_Data_Object *pDataObject, CSG_Data_Object *pCopy, const CSG_String &ID)
1030 {
1031 CSG_Parameter *pParameter = DataObject_Get_Parameter(pCopy, ID);
1032
1033 return( DataObject_Set_Parameter(pDataObject, pParameter) );
1034 }
1035
DataObject_Set_Parameter(CSG_Data_Object * pDataObject,const CSG_String & ID,int Value)1036 bool CSG_Tool::DataObject_Set_Parameter (CSG_Data_Object *pDataObject, const CSG_String &ID, int Value)
1037 {
1038 CSG_Parameters P;
1039
1040 if( DataObject_Get_Parameters(pDataObject, P) && P(ID) )
1041 {
1042 return( P(ID)->Set_Value(Value) && DataObject_Set_Parameter(pDataObject, P(ID)) );
1043 }
1044
1045 return( false );
1046 }
1047
DataObject_Set_Parameter(CSG_Data_Object * pDataObject,const CSG_String & ID,double Value)1048 bool CSG_Tool::DataObject_Set_Parameter (CSG_Data_Object *pDataObject, const CSG_String &ID, double Value)
1049 {
1050 CSG_Parameters P;
1051
1052 if( DataObject_Get_Parameters(pDataObject, P) && P(ID) )
1053 {
1054 return( P(ID)->Set_Value(Value) && DataObject_Set_Parameter(pDataObject, P(ID)) );
1055 }
1056
1057 return( false );
1058 }
1059
DataObject_Set_Parameter(CSG_Data_Object * pDataObject,const CSG_String & ID,void * Value)1060 bool CSG_Tool::DataObject_Set_Parameter (CSG_Data_Object *pDataObject, const CSG_String &ID, void *Value)
1061 {
1062 CSG_Parameters P;
1063
1064 if( DataObject_Get_Parameters(pDataObject, P) && P(ID) )
1065 {
1066 return( P(ID)->Set_Value(Value) && DataObject_Set_Parameter(pDataObject, P(ID)) );
1067 }
1068
1069 return( false );
1070 }
1071
DataObject_Set_Parameter(CSG_Data_Object * pDataObject,const CSG_String & ID,const SG_Char * Value)1072 bool CSG_Tool::DataObject_Set_Parameter (CSG_Data_Object *pDataObject, const CSG_String &ID, const SG_Char *Value)
1073 {
1074 CSG_Parameters P;
1075
1076 if( DataObject_Get_Parameters(pDataObject, P) && P(ID) )
1077 {
1078 return( P(ID)->Set_Value(Value) && DataObject_Set_Parameter(pDataObject, P(ID)) );
1079 }
1080
1081 return( false );
1082 }
1083
DataObject_Set_Parameter(CSG_Data_Object * pDataObject,const CSG_String & ID,double loVal,double hiVal)1084 bool CSG_Tool::DataObject_Set_Parameter (CSG_Data_Object *pDataObject, const CSG_String &ID, double loVal, double hiVal) // Range Parameter
1085 {
1086 CSG_Parameters P;
1087
1088 if( DataObject_Get_Parameters(pDataObject, P) && P(ID) && P(ID)->Get_Type() == PARAMETER_TYPE_Range )
1089 {
1090 return( P(ID)->asRange()->Set_Range(loVal, hiVal) && DataObject_Set_Parameter(pDataObject, P(ID)) );
1091 }
1092
1093 return( false );
1094 }
1095
1096
1097 ///////////////////////////////////////////////////////////
1098 // //
1099 // //
1100 // //
1101 ///////////////////////////////////////////////////////////
1102
1103 //---------------------------------------------------------
1104 /**
1105 * Direct 'set a value' access to this tool's default parameters list.
1106 */
1107 //---------------------------------------------------------
Set_Parameter(const CSG_String & ID,CSG_Parameter * pValue)1108 bool CSG_Tool::Set_Parameter(const CSG_String &ID, CSG_Parameter *pValue) { return( Parameters.Set_Parameter(ID, pValue) ); }
Set_Parameter(const char * ID,CSG_Parameter * pValue)1109 bool CSG_Tool::Set_Parameter(const char *ID, CSG_Parameter *pValue) { return( Parameters.Set_Parameter(ID, pValue) ); }
Set_Parameter(const wchar_t * ID,CSG_Parameter * pValue)1110 bool CSG_Tool::Set_Parameter(const wchar_t *ID, CSG_Parameter *pValue) { return( Parameters.Set_Parameter(ID, pValue) ); }
1111
1112 //---------------------------------------------------------
1113 /**
1114 * Direct 'set a value' access to this tool's default parameters list.
1115 */
1116 //---------------------------------------------------------
Set_Parameter(const CSG_String & ID,int Value,int Type)1117 bool CSG_Tool::Set_Parameter(const CSG_String &ID, int Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
Set_Parameter(const char * ID,int Value,int Type)1118 bool CSG_Tool::Set_Parameter(const char *ID, int Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
Set_Parameter(const wchar_t * ID,int Value,int Type)1119 bool CSG_Tool::Set_Parameter(const wchar_t *ID, int Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
1120
1121 //---------------------------------------------------------
1122 /**
1123 * Direct 'set a value' access to this tool's default parameters list.
1124 */
1125 //---------------------------------------------------------
Set_Parameter(const CSG_String & ID,double Value,int Type)1126 bool CSG_Tool::Set_Parameter(const CSG_String &ID, double Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
Set_Parameter(const char * ID,double Value,int Type)1127 bool CSG_Tool::Set_Parameter(const char *ID, double Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
Set_Parameter(const wchar_t * ID,double Value,int Type)1128 bool CSG_Tool::Set_Parameter(const wchar_t *ID, double Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
1129
1130 //---------------------------------------------------------
1131 /**
1132 * Direct 'set a value' access to this tool's default parameters list.
1133 */
1134 //---------------------------------------------------------
Set_Parameter(const CSG_String & ID,void * Value,int Type)1135 bool CSG_Tool::Set_Parameter(const CSG_String &ID, void *Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
Set_Parameter(const char * ID,void * Value,int Type)1136 bool CSG_Tool::Set_Parameter(const char *ID, void *Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
Set_Parameter(const wchar_t * ID,void * Value,int Type)1137 bool CSG_Tool::Set_Parameter(const wchar_t *ID, void *Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
1138
1139 //---------------------------------------------------------
1140 /**
1141 * Direct 'set a value' access to this tool's default parameters list.
1142 */
1143 //---------------------------------------------------------
Set_Parameter(const CSG_String & ID,const CSG_String & Value,int Type)1144 bool CSG_Tool::Set_Parameter(const CSG_String &ID, const CSG_String &Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
Set_Parameter(const char * ID,const CSG_String & Value,int Type)1145 bool CSG_Tool::Set_Parameter(const char *ID, const CSG_String &Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
Set_Parameter(const wchar_t * ID,const CSG_String & Value,int Type)1146 bool CSG_Tool::Set_Parameter(const wchar_t *ID, const CSG_String &Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
1147
1148 //---------------------------------------------------------
1149 /**
1150 * Direct 'set a value' access to this tool's default parameters list.
1151 */
1152 //---------------------------------------------------------
Set_Parameter(const CSG_String & ID,const char * Value,int Type)1153 bool CSG_Tool::Set_Parameter(const CSG_String &ID, const char *Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
Set_Parameter(const char * ID,const char * Value,int Type)1154 bool CSG_Tool::Set_Parameter(const char *ID, const char *Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
Set_Parameter(const wchar_t * ID,const char * Value,int Type)1155 bool CSG_Tool::Set_Parameter(const wchar_t *ID, const char *Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
1156
1157 //---------------------------------------------------------
1158 /**
1159 * Direct 'set a value' access to this tool's default parameters list.
1160 */
1161 //---------------------------------------------------------
Set_Parameter(const CSG_String & ID,const wchar_t * Value,int Type)1162 bool CSG_Tool::Set_Parameter(const CSG_String &ID, const wchar_t *Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
Set_Parameter(const char * ID,const wchar_t * Value,int Type)1163 bool CSG_Tool::Set_Parameter(const char *ID, const wchar_t *Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
Set_Parameter(const wchar_t * ID,const wchar_t * Value,int Type)1164 bool CSG_Tool::Set_Parameter(const wchar_t *ID, const wchar_t *Value, int Type) { return( Parameters.Set_Parameter(ID, Value, Type) ); }
1165
1166
1167 ///////////////////////////////////////////////////////////
1168 // //
1169 // //
1170 // //
1171 ///////////////////////////////////////////////////////////
1172
1173 //---------------------------------------------------------
1174 /**
1175 * Resets the tools' parameters list. All input and output
1176 * data objects and object lists are cleared and parameter
1177 * defaults are restored.
1178 */
Reset(void)1179 bool CSG_Tool::Reset(void)
1180 {
1181 for(int i=0; i<m_npParameters; i++)
1182 {
1183 m_pParameters[i]->Restore_Defaults(true);
1184 m_pParameters[i]->Reset_Grid_System();
1185 }
1186
1187 return( Parameters.Restore_Defaults(true)
1188 && Parameters.Reset_Grid_System()
1189 );
1190 }
1191
1192 //---------------------------------------------------------
1193 /**
1194 * Resets the tools' grid system, if it has one, which is
1195 * typically the case for all derivatives of CSG_Tool_Grid.
1196 */
Reset_Grid_System(void)1197 bool CSG_Tool::Reset_Grid_System(void)
1198 {
1199 return( Parameters.Reset_Grid_System() );
1200 }
1201
1202 //---------------------------------------------------------
1203 /**
1204 * Sets the tools' grid system, if it has one, which is
1205 * typically the case for all derivatives of CSG_Tool_Grid.
1206 */
Set_Grid_System(const CSG_Grid_System & System)1207 bool CSG_Tool::Set_Grid_System(const CSG_Grid_System &System)
1208 {
1209 return( Parameters.Set_Grid_System(System) );
1210 }
1211
1212
1213 ///////////////////////////////////////////////////////////
1214 // //
1215 // //
1216 // //
1217 ///////////////////////////////////////////////////////////
1218
1219 //---------------------------------------------------------
Update_Parameter_States(void)1220 bool CSG_Tool::Update_Parameter_States(void)
1221 {
1222 _Update_Parameter_States(&Parameters);
1223
1224 for(int i=0; i<Get_Parameters_Count(); i++)
1225 {
1226 _Update_Parameter_States(Get_Parameters(i));
1227 }
1228
1229 return( true );
1230 }
1231
1232 //---------------------------------------------------------
_Update_Parameter_States(CSG_Parameters * pParameters)1233 void CSG_Tool::_Update_Parameter_States(CSG_Parameters *pParameters)
1234 {
1235 if( pParameters )
1236 {
1237 for(int i=0; i<pParameters->Get_Count(); i++)
1238 {
1239 CSG_Parameter *pParameter = pParameters->Get_Parameter(i);
1240
1241 if( pParameter->Get_Type() == PARAMETER_TYPE_Parameters )
1242 {
1243 _Update_Parameter_States(pParameter->asParameters());
1244 }
1245 else
1246 {
1247 On_Parameters_Enable(pParameters, pParameter);
1248 }
1249 }
1250 }
1251 }
1252
1253
1254 ///////////////////////////////////////////////////////////
1255 // //
1256 // Script //
1257 // //
1258 ///////////////////////////////////////////////////////////
1259
1260 //---------------------------------------------------------
Get_Script(TSG_Tool_Script_Type Type,bool bHeader,bool bAllParameters)1261 CSG_String CSG_Tool::Get_Script(TSG_Tool_Script_Type Type, bool bHeader, bool bAllParameters)
1262 {
1263 switch( Type )
1264 {
1265 case TOOL_SCRIPT_CMD_SHELL: return( _Get_Script_CMD ( bHeader, bAllParameters, Type) );
1266 case TOOL_SCRIPT_CMD_BATCH: return( _Get_Script_CMD ( bHeader, bAllParameters, Type) );
1267 case TOOL_SCRIPT_PYTHON : return( _Get_Script_Python ( bHeader, bAllParameters ) );
1268 case TOOL_SCRIPT_CHAIN : return( CSG_Tool_Chain::Get_Script(this, bHeader, bAllParameters ) );
1269 }
1270
1271 return( "" );
1272 }
1273
1274
1275 ///////////////////////////////////////////////////////////
1276 // //
1277 ///////////////////////////////////////////////////////////
1278
1279 //---------------------------------------------------------
_Get_Script_CMD(bool bHeader,bool bAllParameters,TSG_Tool_Script_Type Type)1280 CSG_String CSG_Tool::_Get_Script_CMD(bool bHeader, bool bAllParameters, TSG_Tool_Script_Type Type)
1281 {
1282 CSG_String Script;
1283
1284 if( bHeader )
1285 {
1286 switch( Type )
1287 {
1288 case TOOL_SCRIPT_CMD_BATCH: // DOS/Windows Batch Script
1289 Script += "@ECHO OFF\n\n";
1290 Script += "PUSHD %~dp0\n\n";
1291 Script += "REM SET SAGA_TLB=C:\\MyTools\n\n";
1292 Script += "SET SAGA_CMD=" + SG_UI_Get_Application_Path(true) + "saga_cmd.exe\n\n";
1293 Script += "REM Tool: " + Get_Name() + "\n\n";
1294 Script += "%SAGA_CMD%";
1295 break;
1296
1297 default : // Bash Shell Script
1298 Script += "#!/bin/bash\n\n";
1299 Script += "# export SAGA_TLB=/home/myhome/mytools\n\n";
1300 Script += "# tool: " + Get_Name() + "\n\n";
1301 Script += "saga_cmd";
1302 break;
1303 }
1304 }
1305 else
1306 {
1307 Script += "saga_cmd";
1308 }
1309
1310 //-----------------------------------------------------
1311 Script += Get_Library().Contains(" ") // white space? use quotation marks!
1312 ? " \"" + Get_Library() + "\""
1313 : " " + Get_Library();
1314
1315 Script += Get_ID().Contains (" ") // white space? use quotation marks!
1316 ? " \"" + Get_ID () + "\""
1317 : " " + Get_ID ();
1318
1319 _Get_Script_CMD(Script, Get_Parameters(), bAllParameters);
1320
1321 for(int i=0; i<Get_Parameters_Count(); i++)
1322 {
1323 _Get_Script_CMD(Script, Get_Parameters(i), bAllParameters);
1324 }
1325
1326 //-----------------------------------------------------
1327 if( bHeader && Type == TOOL_SCRIPT_CMD_BATCH )
1328 {
1329 Script += "\n\nPAUSE\n";
1330 }
1331
1332 return( Script );
1333 }
1334
1335 //---------------------------------------------------------
_Get_Script_CMD(CSG_String & Script,CSG_Parameters * pParameters,bool bAllParameters)1336 void CSG_Tool::_Get_Script_CMD(CSG_String &Script, CSG_Parameters *pParameters, bool bAllParameters)
1337 {
1338 #define GET_ID1(p) (p->Get_Parameters()->Get_Identifier().Length() > 0 \
1339 ? CSG_String::Format("%s_%s", p->Get_Parameters()->Get_Identifier().c_str(), p->Get_Identifier()) \
1340 : CSG_String::Format(p->Get_Identifier())).c_str()
1341
1342 #define GET_ID2(p, s) CSG_String::Format("%s_%s", GET_ID1(p), s).c_str()
1343
1344 #ifdef _SAGA_MSW
1345 CSG_String Prefix = " ^\n -";
1346 #else
1347 CSG_String Prefix = " \\\n -";
1348 #endif
1349
1350 //-----------------------------------------------------
1351 for(int iParameter=0; iParameter<pParameters->Get_Count(); iParameter++)
1352 {
1353 CSG_Parameter *p = pParameters->Get_Parameter(iParameter);
1354
1355 if( !bAllParameters && (!p->is_Enabled(false) || p->is_Information() || !p->do_UseInCMD()) )
1356 {
1357 continue;
1358 }
1359
1360 switch( p->Get_Type() )
1361 {
1362 default:
1363 break;
1364
1365 case PARAMETER_TYPE_Bool :
1366 Script += Prefix + CSG_String::Format("%s=%d", GET_ID1(p), p->asBool() ? 1 : 0);
1367 break;
1368
1369 case PARAMETER_TYPE_Int :
1370 case PARAMETER_TYPE_Choice :
1371 case PARAMETER_TYPE_Table_Field :
1372 Script += Prefix + CSG_String::Format("%s=%d", GET_ID1(p), p->asInt());
1373 break;
1374
1375 case PARAMETER_TYPE_Choices :
1376 case PARAMETER_TYPE_Table_Fields:
1377 if( p->asString() && *p->asString() )
1378 Script += Prefix + CSG_String::Format("%s=%s", GET_ID1(p), p->asString());
1379 break;
1380
1381 case PARAMETER_TYPE_Double :
1382 case PARAMETER_TYPE_Degree :
1383 Script += Prefix + CSG_String::Format("%s=%g", GET_ID1(p), p->asDouble());
1384 break;
1385
1386 case PARAMETER_TYPE_Range :
1387 Script += Prefix + CSG_String::Format("%s=%g", GET_ID2(p, SG_T("MIN")), p->asRange()->Get_Min());
1388 Script += Prefix + CSG_String::Format("%s=%g", GET_ID2(p, SG_T("MAX")), p->asRange()->Get_Max());
1389 break;
1390
1391 case PARAMETER_TYPE_Date :
1392 case PARAMETER_TYPE_String :
1393 case PARAMETER_TYPE_Text :
1394 case PARAMETER_TYPE_FilePath :
1395 Script += Prefix + CSG_String::Format("%s=\"%s\"", GET_ID1(p), p->asString());
1396 break;
1397
1398 case PARAMETER_TYPE_FixedTable :
1399 Script += Prefix + CSG_String::Format("%s=%s", GET_ID1(p), p->asString());
1400 break;
1401
1402 case PARAMETER_TYPE_Grid_System :
1403 if( p->Get_Children_Count() == 0 )
1404 {
1405 Script += Prefix + CSG_String::Format("%s=%d", GET_ID2(p, SG_T("NX")), p->asGrid_System()->Get_NX());
1406 Script += Prefix + CSG_String::Format("%s=%d", GET_ID2(p, SG_T("NY")), p->asGrid_System()->Get_NY());
1407 Script += Prefix + CSG_String::Format("%s=%g", GET_ID2(p, SG_T( "X")), p->asGrid_System()->Get_XMin());
1408 Script += Prefix + CSG_String::Format("%s=%g", GET_ID2(p, SG_T( "Y")), p->asGrid_System()->Get_YMin());
1409 Script += Prefix + CSG_String::Format("%s=%g", GET_ID2(p, SG_T( "D")), p->asGrid_System()->Get_Cellsize());
1410 }
1411 break;
1412
1413 case PARAMETER_TYPE_DataObject_Output:
1414 case PARAMETER_TYPE_Grid :
1415 case PARAMETER_TYPE_Grids :
1416 case PARAMETER_TYPE_Table :
1417 case PARAMETER_TYPE_Shapes :
1418 case PARAMETER_TYPE_TIN :
1419 case PARAMETER_TYPE_PointCloud :
1420 if( p->is_Input() )
1421 {
1422 Script += Prefix + CSG_String::Format("%s=\"%s\"", GET_ID1(p), SG_Get_Data_Manager().Exists(p->asDataObject()) && p->asDataObject()->Get_File_Name() ? p->asDataObject()->Get_File_Name() : SG_T("input file"));
1423 }
1424 else
1425 {
1426 CSG_String ext;
1427
1428 switch( p->Get_DataObject_Type() )
1429 {
1430 case SG_DATAOBJECT_TYPE_Grid : ext = "sg-grd-z"; break;
1431 case SG_DATAOBJECT_TYPE_Grids : ext = "sg-gds-z"; break;
1432 case SG_DATAOBJECT_TYPE_Table : ext = "txt" ; break;
1433 case SG_DATAOBJECT_TYPE_Shapes : ext = "geojson" ; break;
1434 case SG_DATAOBJECT_TYPE_PointCloud: ext = "sg-pts-z"; break;
1435 case SG_DATAOBJECT_TYPE_TIN : ext = "geojson" ; break;
1436 default : ext = "dat" ; break;
1437 }
1438
1439 Script += Prefix + CSG_String::Format("%s=\"%s.%s\"", GET_ID1(p), p->Get_Name(), ext.c_str());
1440 }
1441 break;
1442
1443 case PARAMETER_TYPE_Grid_List :
1444 case PARAMETER_TYPE_Grids_List :
1445 case PARAMETER_TYPE_Table_List :
1446 case PARAMETER_TYPE_Shapes_List :
1447 case PARAMETER_TYPE_TIN_List :
1448 case PARAMETER_TYPE_PointCloud_List :
1449 if( p->is_Input() )
1450 {
1451 Script += Prefix + CSG_String::Format("%s=", GET_ID1(p));
1452
1453 if( p->asList()->Get_Item_Count() == 0 )
1454 {
1455 Script += "file(s)";
1456 }
1457 else
1458 {
1459 Script += SG_File_Exists(p->asList()->Get_Item(0)->Get_File_Name())
1460 ? p->asList()->Get_Item(0)->Get_File_Name() : _TL("memory");
1461
1462 for(int iObject=1; iObject<p->asList()->Get_Item_Count(); iObject++)
1463 {
1464 Script += ";";
1465 Script += SG_File_Exists(p->asList()->Get_Item(iObject)->Get_File_Name())
1466 ? p->asList()->Get_Item(iObject)->Get_File_Name() : _TL("memory");
1467 }
1468 }
1469 }
1470 break;
1471 }
1472 }
1473 }
1474
1475
1476 ///////////////////////////////////////////////////////////
1477 // //
1478 ///////////////////////////////////////////////////////////
1479
1480 //---------------------------------------------------------
_Get_Script_Python(bool bHeader,bool bAllParameters)1481 CSG_String CSG_Tool::_Get_Script_Python(bool bHeader, bool bAllParameters)
1482 {
1483 CSG_String Script, Name(Get_Name()); Name.Replace(" ", "_"); Name.Replace("(", ""); Name.Replace(")", ""); Name.Replace("[", ""); Name.Replace("]", ""); Name.Replace(".", "");
1484
1485 //-----------------------------------------------------
1486 if( bHeader )
1487 {
1488 Script += "#! /usr/bin/env python\n";
1489 Script += "\n";
1490 Script += "#_________________________________________\n";
1491 Script += "##########################################\n";
1492 Script += "# Initialize the environment...\n";
1493 Script += "\n";
1494 #ifdef _SAGA_MSW
1495 CSG_String AppPath = SG_UI_Get_Application_Path(true); AppPath.Replace("\\", "/");
1496 Script += "# Windows: set/adjust the 'SAGA_PATH' environment variable before importing saga_helper\n";
1497 Script += "import os\n";
1498 Script += "if os.name == 'nt' and os.getenv('SAGA_PATH') is None:\n";
1499 Script += " os.environ['SAGA_PATH'] = '" + AppPath + "'\n";
1500 Script += "import saga_helper, saga_api\n";
1501 #else
1502 Script += "import os, saga_helper, saga_api\n";
1503 #endif // _SAGA_MSW
1504 Script += "\n";
1505 Script += "saga_helper.Initialize(True)\n";
1506 Script += "\n";
1507 Script += "\n";
1508 Script += "#_________________________________________\n";
1509 Script += "##########################################\n";
1510 Script += "def Run_" + Name + "(File):\n";
1511 }
1512
1513 //-----------------------------------------------------
1514 Script += " Tool = saga_api.SG_Get_Tool_Library_Manager().Get_Tool('" + Get_Library() + "', '" + Get_ID() + "')\n";
1515 Script += " if Tool == None:\n";
1516 Script += " print('Failed to request tool: " + Get_Name() + "')\n";
1517 Script += " return False\n";
1518 Script += " Tool.Reset()\n";
1519 Script += "\n";
1520
1521 //-------------------------------------------------
1522 _Get_Script_Python(Script, Get_Parameters(), bAllParameters);
1523
1524 for(int iParameters=0; iParameters<Get_Parameters_Count(); iParameters++)
1525 {
1526 _Get_Script_Python(Script, Get_Parameters(iParameters), bAllParameters, Get_Parameters(iParameters)->Get_Identifier());
1527 }
1528
1529 //-------------------------------------------------
1530 Script += "\n";
1531 Script += " if Tool.Execute() == False:\n";
1532 Script += " print('failed to execute tool: ' + Tool.Get_Name().c_str())\n";
1533 Script += " return False\n";
1534 Script += "\n";
1535 Script += " #_____________________________________\n";
1536 Script += " # Save results to file:\n";
1537 Script += " Path = os.path.split(File)[0] + os.sep\n";
1538
1539 for(int iParameter=0; iParameter<Get_Parameters()->Get_Count(); iParameter++)
1540 {
1541 CSG_Parameter *p = Get_Parameters()->Get_Parameter(iParameter);
1542
1543 if( p->is_Output() )
1544 {
1545 CSG_String id(p->Get_Identifier()), ext;
1546
1547 switch( p->Get_DataObject_Type() )
1548 {
1549 case SG_DATAOBJECT_TYPE_Grid : ext = " + '.sg-grd-z'"; break;
1550 case SG_DATAOBJECT_TYPE_Grids : ext = " + '.sg-gds-z'"; break;
1551 case SG_DATAOBJECT_TYPE_Table : ext = " + '.txt'" ; break;
1552 case SG_DATAOBJECT_TYPE_Shapes : ext = " + '.geojson'" ; break;
1553 case SG_DATAOBJECT_TYPE_PointCloud: ext = " + '.sg-pts-z'"; break;
1554 case SG_DATAOBJECT_TYPE_TIN : ext = " + '.geojson'" ; break;
1555 default : ext = "" ; break;
1556 }
1557
1558 Script += "\n";
1559
1560 if( p->is_DataObject() )
1561 {
1562 Script += " Data = Tool.Get_Parameter('" + id + "').asDataObject()\n";
1563 Script += " Data.Save(Path + Data.Get_Name()" + ext + ")\n";
1564 }
1565 else if( p->is_DataObject_List() )
1566 {
1567 Script += " List = Tool.Get_Parameter('" + id + "').asList()\n";
1568 Script += " Name = Path + List.Get_Name()\n";
1569 Script += " for i in range(0, List.Get_Data_Count()):\n";
1570 Script += " List.Get_Data(i).Save(Name + str(i)" + ext + ")\n";
1571 }
1572 }
1573 }
1574
1575 //-----------------------------------------------------
1576 if( bHeader )
1577 {
1578 Script += "\n";
1579 Script += " #_____________________________________\n";
1580 Script += " saga_api.SG_Get_Data_Manager().Delete_All() # job is done, free memory resources\n";
1581 Script += "\n";
1582 Script += " return True\n";
1583 Script += "\n";
1584 Script += "\n";
1585 Script += "#_________________________________________\n";
1586 Script += "##########################################\n";
1587 Script += "if __name__ == '__main__':\n";
1588 Script += " print('This is a simple template for using a SAGA tool through Python.')\n";
1589 Script += " print('Please edit the script to make it work properly before using it!')\n";
1590 Script += " import sys\n";
1591 Script += " sys.exit()\n";
1592 Script += "\n";
1593 Script += " # For a single file based input it might look like following:\n";
1594 Script += " File = sys.argv[1]\n";
1595 Script += " Run_" + Name + "(File)\n";
1596 }
1597
1598 return( Script );
1599 }
1600
1601 //---------------------------------------------------------
_Get_Script_Python(CSG_String & Script,CSG_Parameters * pParameters,bool bAllParameters,const CSG_String & Prefix)1602 void CSG_Tool::_Get_Script_Python(CSG_String &Script, CSG_Parameters *pParameters, bool bAllParameters, const CSG_String &Prefix)
1603 {
1604 for(int iParameter=0; iParameter<pParameters->Get_Count(); iParameter++)
1605 {
1606 CSG_Parameter *p = pParameters->Get_Parameter(iParameter);
1607
1608 if( !bAllParameters && (!p->is_Enabled(false) || p->is_Information() || !p->do_UseInCMD()) )
1609 {
1610 continue;
1611 }
1612
1613 CSG_String ID(p->Get_Identifier());
1614
1615 if( !Prefix.is_Empty() )
1616 {
1617 ID.Prepend(Prefix + ".");
1618 }
1619
1620 switch( p->Get_Type() )
1621 {
1622 default:
1623 break;
1624
1625 case PARAMETER_TYPE_Bool :
1626 Script += CSG_String::Format(" Tool.Set_Parameter('%s', %s)\n", ID.c_str(), p->asBool() ? SG_T("True") : SG_T("False"));
1627 break;
1628
1629 case PARAMETER_TYPE_Int :
1630 Script += CSG_String::Format(" Tool.Set_Parameter('%s', %d)\n", ID.c_str(), p->asInt());
1631 break;
1632
1633 case PARAMETER_TYPE_Choice :
1634 Script += CSG_String::Format(" Tool.Set_Parameter('%s', %d) # '%s'\n", ID.c_str(), p->asInt(), p->asString());
1635 break;
1636
1637 case PARAMETER_TYPE_Choices :
1638 case PARAMETER_TYPE_Table_Field :
1639 case PARAMETER_TYPE_Table_Fields :
1640 Script += CSG_String::Format(" Tool.Set_Parameter('%s', '%s')\n", ID.c_str(), p->asString());
1641 break;
1642
1643 case PARAMETER_TYPE_Double :
1644 case PARAMETER_TYPE_Degree :
1645 Script += CSG_String::Format(" Tool.Set_Parameter('%s', %g)\n", ID.c_str(), p->asDouble());
1646 break;
1647
1648 case PARAMETER_TYPE_Range :
1649 Script += CSG_String::Format(" Tool.Set_Parameter('%s.MIN', %g)\n", ID.c_str(), p->asRange()->Get_Min());
1650 Script += CSG_String::Format(" Tool.Set_Parameter('%s.MAX', %g)\n", ID.c_str(), p->asRange()->Get_Max());
1651 break;
1652
1653 case PARAMETER_TYPE_Date :
1654 case PARAMETER_TYPE_String :
1655 case PARAMETER_TYPE_Text :
1656 case PARAMETER_TYPE_FilePath :
1657 Script += CSG_String::Format(" Tool.Set_Parameter('%s', '%s')\n", ID.c_str(), p->asString());
1658 break;
1659
1660 case PARAMETER_TYPE_FixedTable :
1661 Script += CSG_String::Format(" Tool.Set_Parameter('%s', saga_api.SG_Create_Table('table.txt'))\n", ID.c_str());
1662 break;
1663
1664 case PARAMETER_TYPE_Grid_System :
1665 if( p->Get_Children_Count() == 0 )
1666 {
1667 Script += CSG_String::Format(" Tool.Set_Parameter('%s', saga_api.CSG_Grid_System(%g, %g, %g, %d, %d))\n", ID.c_str(),
1668 p->asGrid_System()->Get_Cellsize(),
1669 p->asGrid_System()->Get_XMin(), p->asGrid_System()->Get_YMin(),
1670 p->asGrid_System()->Get_NX (), p->asGrid_System()->Get_NY ()
1671 );
1672 }
1673 break;
1674
1675 case PARAMETER_TYPE_Grid :
1676 case PARAMETER_TYPE_Grids :
1677 case PARAMETER_TYPE_Table :
1678 case PARAMETER_TYPE_Shapes :
1679 case PARAMETER_TYPE_TIN :
1680 case PARAMETER_TYPE_PointCloud :
1681 if( p->is_Input() )
1682 {
1683 Script += CSG_String::Format(" Tool.Set_Parameter('%s', saga_api.SG_Get_Data_Manager().Add('%s input file%s'))\n", ID.c_str(),
1684 SG_Get_DataObject_Name(p->Get_DataObject_Type()).c_str(), p->is_Optional() ? SG_T(", optional") : SG_T("")
1685 );
1686 }
1687 else if( p->is_Output() && p->is_Optional() )
1688 {
1689 Script += CSG_String::Format(" Tool.Set_Parameter('%s', saga_api.SG_Get_Create_Pointer()) # optional output, remove this line, if you don't want to create it\n", ID.c_str());
1690 }
1691 break;
1692
1693 case PARAMETER_TYPE_Grid_List :
1694 case PARAMETER_TYPE_Grids_List :
1695 case PARAMETER_TYPE_Table_List :
1696 case PARAMETER_TYPE_Shapes_List :
1697 case PARAMETER_TYPE_TIN_List :
1698 case PARAMETER_TYPE_PointCloud_List:
1699 if( p->is_Input() )
1700 {
1701 Script += CSG_String::Format(" Tool.Get_Parameter('%s').asList().Add_Item('%s input list%s')\n", ID.c_str(),
1702 SG_Get_DataObject_Name(p->Get_DataObject_Type()).c_str(), p->is_Optional() ? SG_T(", optional") : SG_T("")
1703 );
1704 }
1705 break;
1706
1707 case PARAMETER_TYPE_Parameters :
1708 _Get_Script_Python(Script, p->asParameters(), bAllParameters, ID);
1709 break;
1710 }
1711 }
1712 }
1713
1714
1715 ///////////////////////////////////////////////////////////
1716 // //
1717 // History //
1718 // //
1719 ///////////////////////////////////////////////////////////
1720
1721 //---------------------------------------------------------
_Get_Output_History(void)1722 CSG_MetaData CSG_Tool::_Get_Output_History(void)
1723 {
1724 CSG_MetaData History;
1725
1726 History.Set_Name(SG_META_HISTORY);
1727 History.Add_Property("saga-version", SAGA_VERSION);
1728
1729 if( SG_Get_History_Depth() )
1730 {
1731 CSG_MetaData *pTool = History.Add_Child("TOOL");
1732
1733 pTool->Add_Property("library", Get_Library());
1734 pTool->Add_Property("id" , Get_ID ());
1735 pTool->Add_Property("name" , Get_Name ());
1736
1737 Parameters.Set_History(*pTool);
1738
1739 pTool->Add_Children(History_Supplement);
1740
1741 CSG_MetaData *pOutput = pTool->Add_Child("OUTPUT");
1742 pOutput->Add_Property("type", "");
1743 pOutput->Add_Property("id" , "");
1744 pOutput->Add_Property("name", "");
1745
1746 pTool->Del_Children(SG_Get_History_Depth(), SG_T("TOOL"));
1747 }
1748
1749 return( History );
1750 }
1751
1752 //---------------------------------------------------------
_Set_Output_History(void)1753 void CSG_Tool::_Set_Output_History(void)
1754 {
1755 CSG_MetaData History(_Get_Output_History());
1756
1757 //-----------------------------------------------------
1758 for(int j=-1; j<Get_Parameters_Count(); j++)
1759 {
1760 CSG_Parameters *pParameters = j < 0 ? &Parameters : Get_Parameters(j);
1761
1762 for(int i=0; i<pParameters->Get_Count(); i++)
1763 {
1764 CSG_Parameter *pParameter = pParameters->Get_Parameter(i);
1765
1766 if( pParameter->is_Output() )//&& (pParameter->is_Enabled() || !has_GUI()) )
1767 {
1768 DataObject_Set_History(pParameter, &History);
1769 }
1770 }
1771 }
1772 }
1773
1774 //---------------------------------------------------------
DataObject_Set_History(CSG_Parameter * pParameter,CSG_MetaData * pHistory)1775 bool CSG_Tool::DataObject_Set_History(CSG_Parameter *pParameter, CSG_MetaData *pHistory)
1776 {
1777 if( !pParameter )
1778 {
1779 return( false );
1780 }
1781
1782 //-----------------------------------------------------
1783 CSG_MetaData History;
1784
1785 if( !pHistory )
1786 {
1787 History = _Get_Output_History();
1788
1789 pHistory = &History;
1790 }
1791
1792 //-----------------------------------------------------
1793 CSG_MetaData *pOutput = pHistory->Get_Child("TOOL") ? pHistory->Get_Child("TOOL")->Get_Child("OUTPUT") : NULL;
1794
1795 if( pOutput )
1796 {
1797 pOutput->Set_Property("type", pParameter->Get_Type_Identifier());
1798 pOutput->Set_Property("id" , pParameter->Get_Identifier ());
1799 pOutput->Set_Property("name", pParameter->Get_Name ());
1800 }
1801
1802 //-----------------------------------------------------
1803 if( pParameter->is_DataObject() )
1804 {
1805 if( pParameter->asDataObject() )
1806 {
1807 if( pOutput )
1808 {
1809 pOutput->Set_Content(pParameter->asDataObject()->Get_Name());
1810 }
1811
1812 pParameter->asDataObject()->Get_History().Assign(*pHistory);
1813
1814 return( true );
1815 }
1816 }
1817
1818 //-----------------------------------------------------
1819 else if( pParameter->is_DataObject_List() )
1820 {
1821 for(int j=0; j<pParameter->asList()->Get_Item_Count(); j++)
1822 {
1823 if( pOutput )
1824 {
1825 pOutput->Set_Content(pParameter->asList()->Get_Item(j)->Get_Name());
1826 }
1827
1828 pParameter->asList()->Get_Item(j)->Get_History().Assign(*pHistory);
1829 }
1830
1831 return( true );
1832 }
1833
1834 //-----------------------------------------------------
1835 return( false );
1836 }
1837
1838
1839 ///////////////////////////////////////////////////////////
1840 // //
1841 // //
1842 // //
1843 ///////////////////////////////////////////////////////////
1844
1845 //---------------------------------------------------------
1846