wxArt2D
mastertoolgroups2.cpp
1 /*! \file editor/src/mastertoolgroups.cpp
2  \author Klaas Holwerda
3  \date Created 22/04/2012
4 
5  Copyright: 2012-2012 (c) Klaas Holwerda
6 
7  Licence: wxWidgets Licence
8 
9  RCS-ID: $Id: mastertoolgroups.cpp,v 1.13 2009/04/23 19:35:23 titato Exp $
10 */
11 
12 #include "a2dprec.h"
13 
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17 
18 #ifndef WX_PRECOMP
19 #include "wx/wx.h"
20 #endif
21 
22 #include "wx/canvas/canmod.h"
23 //#include "wx/filename.h"
24 
25 #include <float.h>
26 #include "wx/canvas/sttool.h"
27 #include "wx/canvas/sttool2.h"
29 
30 //----------------------------------------------------------------------------
31 // a2dMasterTagGroups2
32 //----------------------------------------------------------------------------
33 
34 IMPLEMENT_CLASS( a2dMasterTagGroups2 , a2dMasterDrawBase )
35 
36 BEGIN_EVENT_TABLE( a2dMasterTagGroups2 , a2dMasterDrawBase )
37  EVT_MOUSE_EVENTS( a2dMasterTagGroups2 ::OnMouseEvent )
38  EVT_CHAR( a2dMasterTagGroups2 ::OnChar )
39  EVT_KEY_DOWN( a2dMasterTagGroups2 ::OnKeyDown )
40  EVT_KEY_UP( a2dMasterTagGroups2 ::OnKeyUp )
41 END_EVENT_TABLE()
42 
43 a2dMasterTagGroups2 ::a2dMasterTagGroups2 ( a2dStToolContr* controller ): a2dMasterDrawBase( controller )
44 {
45  controller->SetDefaultBehavior( controller->GetDefaultBehavior() | wxTC_NoDefaultKeys | wxTC_NoDefaultMouseActions );
46  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_Select );
47 }
48 
49 a2dMasterTagGroups2 ::~a2dMasterTagGroups2 ()
50 {
51 }
52 
54 {
55 }
56 
58 {
60  m_toolBusy = false;
61 }
62 
64 {
66 
67  if ( selected )
68  {
69  DeselectAll();
70  }
71  if( GetBusy() && m_dragStarted )
72  {
73  switch( m_mode )
74  {
75  case mode_zoom:
76  case mode_select:
77  case mode_cntrlselect:
78  {
79  break;
80  }
81  default:
82  break;
83  }
84  }
85 
87 }
88 
89 void a2dMasterTagGroups2::OnChar( wxKeyEvent& event )
90 {
91  //wxLogDebug(wxT("key %d"), event.GetKeyCode());
93 
95 
96  if ( selected )
97  {
98  event.Skip();
99  }
100  else if( GetBusy() && m_dragStarted )
101  {
102  switch( m_mode )
103  {
104  case mode_zoom:
105  case mode_select:
106  case mode_cntrlselect:
107  {
108  break;
109  }
110  default:
111  event.Skip();
112  break;
113  }
114  }
115  else
116  event.Skip();
117 }
118 
119 void a2dMasterTagGroups2 ::OnKeyDown( wxKeyEvent& event )
120 {
121  if ( !m_active )
122  {
123  event.Skip();
124  return;
125  }
126  event.Skip();
127 }
128 
129 void a2dMasterTagGroups2 ::OnKeyUp( wxKeyEvent& event )
130 {
131  if ( !m_active )
132  {
133  event.Skip();
134  return;
135  }
136  event.Skip();
137 }
138 
139 void a2dMasterTagGroups2 ::OnMouseEvent( wxMouseEvent& event )
140 {
141  //MouseDump( event, "OnM " );
142 
143  if ( !m_active )
144  {
145  event.Skip();
146  return;
147  }
148  m_x = event.GetX();
149  m_y = event.GetY();
150 
152 
153  //GetDrawingPart()->Update( a2dCANVIEW_UPDATE_PENDING );
154  a2dIterC ic( GetDrawingPart() );
155  ic.SetLayer( wxLAYER_ALL );
156  ic.SetObjectFilter( new a2dCanvasObjectFilterLayerMask( wxLAYER_ALL, a2dCanvasOFlags::VISIBLE | a2dCanvasOFlags::SELECTABLE ) );
157  a2dHitEvent hitinfo( m_xwprev, m_ywprev, false, a2dCANOBJHITOPTION_NONE, true );
158  hitinfo.m_option = a2dCANOBJHITOPTION_LAYERS;
159  //at the top level the group its matrix is to be ignored.
160  //Since it is normally NOT ignored within a2dCanvasObject, force an inverse.
161  hitinfo.m_xyRelToChildren = false;
162 
163  if ( event.LeftDClick() && !m_toolBusy )
164  {
165  a2dCanvasObject* hit = m_modehit; //reuse from the LeftDown event.
166  if ( hit )
167  {
169  m_modehit = hit;
170 
171  if ( (wire && wire->GetSelected()) || !wire )
172  {
173  hit->SetSelected( m_modehitLastSelectState );
174  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
175  m_mode = mode_edit;
176  PushEditTool( m_modehit );
177  }
178  }
179  }
180  else if ( event.Dragging() && m_toolBusy && !m_dragStarted )
181  {
182  //we assume dragging starts for real if 5 pixels shift.
183  if ( abs( m_x - m_dragstartx ) >= 5 || abs( m_y - m_dragstarty ) >= 5 )
184  {
185  a2dCanvasObject* hit = m_modehit; //use last hit at LeftDown
186  if ( event.ControlDown() && !event.ShiftDown() )
187  {
188  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
189  m_mode = mode_cntrlselect;
190  m_dragStarted = true;
191  }
192  else if ( !event.ControlDown() && event.ShiftDown() )
193  {
194  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
195  m_mode = mode_select;
196  m_dragStarted = true;
197  }
198  else
199  {
200  //both control and shift or non
201  if( hit && hit->GetDraggable() )
202  {
203  if ( hit->GetSelected() )
204  {
205  m_dragStarted = true;
206 
207  if ( event.ControlDown() && event.ShiftDown() )
208  {
209  m_mode = mode_copymulti;
210  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Copy ) );
211  }
212  else //no shift no control
213  {
214  m_mode = mode_dragmulti;
215  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
216  }
217  }
218  else
219  {
220  m_mode = mode_drag;
221  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
222  }
223  }
224  else
225  {
226  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
227  m_mode = mode_select;
228  m_modehit = hit;//NULL;
229  }
230  }
231 
232  m_toolBusy = false;
233  switch( m_mode )
234  {
235  case mode_cntrlselect:
236  DeselectAll();
237  m_toolBusy = true;
238  event.Skip();
239  break;
240  case mode_select:
241  break;
242  case mode_dragmulti:
243  {
244  PushDragMultiTool( m_modehit );
245  //event.Skip();
246  break;
247  }
248  case mode_copymulti:
249  {
250  PushCopyMultiTool( m_modehit );
251  //event.Skip();
252  break;
253  }
254  case mode_drag:
255  {
256  PushDragTool( m_modehit );
257  //event.Skip();
258  break;
259  }
260  case mode_copy:
261  {
262  PushCopyTool( m_modehit );
263  //event.Skip();
264  break;
265  }
266  default:
267  m_toolBusy = true;
268  break;
269  }
270  }
271  }
272  else if ( event.Dragging() && m_toolBusy && m_dragStarted )
273  {
274  }
275  else if ( event.Moving() && !m_toolBusy )
276  {
277  m_mode = mode_none;
278  m_modehit = 0;
279  m_modehitinfo = a2dHit();
280  a2dCanvasObject* hit = GetDrawingPart()->GetShowObject()->ChildIsHitWorld( ic, hitinfo, true );
281  GetDrawing()->GetHabitat()->GetConnectionGenerator()->SetPinsToBeginState( GetDrawingPart()->GetShowObject() );
282 
283  if ( !event.ControlDown() && event.ShiftDown() )
284  {
285  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
286  if ( hit )
287  m_modehit = hit;
288  m_mode = mode_select;
289  }
290  else
291  {
292  if ( hit )
293  {
294  // Check if there is an unconnected pin
295  // This has highest priority
296  a2dPin* pin = NULL;
297  a2dHit how2;
298 
300 
301  if ( wire && wire->GetSelected() || m_vertexSegmentEdit )
302  {
303  int i;
304  float minDist = FLT_MAX;
305  for( i = 0; i < hitinfo.m_extended.size(); i++ )
306  {
307  a2dWirePolylineL* wire2 = wxDynamicCast( hitinfo.m_extended[i].GetObject(), a2dWirePolylineL );
308  if( wire2 && hitinfo.m_extended[i].GetHitType().m_distance < minDist && hitinfo.m_extended[i].GetHitType().IsStrokeHit() )
309  //if( wire2 && hitinfo.m_extended[i].GetHitType().m_distance < minDist && hitinfo.m_extended[i].GetHitType().IsDirectStrokeHit() )
310  {
311  wire = wire2;
312  how2 = hitinfo.m_extended[i].GetHitType();
313  minDist = how2.m_distance;
314  }
315  }
316 
317  if ( wire )
318  {
319  // wire editing mode
320  // check, where the wire was hit:
321  m_modehit = wire;
322  m_modehitinfo = how2;
323  switch( how2.m_stroke2 )
324  {
325  case a2dHit::stroke2_vertex:
326  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireVertex ) );
327  m_mode = mode_editwire_vertex;
328  break;
329  case a2dHit::stroke2_edgehor:
330  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegmentHorizontal ) );
331  m_mode = mode_editwire_segmenthorizontal;
332  break;
333  case a2dHit::stroke2_edgevert:
334  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegmentVertical ) );
335  m_mode = mode_editwire_segmentvertical;
336  break;
337  case a2dHit::stroke2_edgeother:
338  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_WireSegmentInsert ) );
339  m_mode = mode_editwire_segmentinsert;
340  break;
341  default:
342  m_modehit = NULL;
343  m_modehitinfo = a2dHit();
344  }
345  }
346  }
347  else if ( wire )
348  {
349  // m_connectionGenerator.
350  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
352 
353  pin = GetDrawing()->GetHabitat()->GetConnectionGenerator()->
354  SearchPinForStartWire( GetDrawingPart()->GetShowObject(), m_xwprev, m_ywprev, a2dPinClass::Any, GetHitMargin() );
355 
356  if( event.ControlDown() && pin && !pin->IsTemporaryPin() )
357  {
358  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
359  m_mode = mode_move_pin;
360  m_modehit = pin;
361  }
362  else
363  {
364  // wire drawing mode
365  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
366  m_mode = mode_drawwire;
367  m_modehit = pin;
368  }
369 
370  }
371  else
372  {
373  if ( !event.ShiftDown() && !event.ControlDown() )
374  {
375  //While moving event, there is no wire nor pin yet, therefore we can just feedback possible pin connection, based on the
376  // m_connectionGenerator.
377  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
379 
380  pin = GetDrawing()->GetHabitat()->GetConnectionGenerator()->
381  SearchPinForStartWire( GetDrawingPart()->GetShowObject(), m_xwprev, m_ywprev, a2dPinClass::Any, GetHitMargin() );
382 
383  if ( pin )
384  {
386  if ( wire && wire->GetSelected() || m_vertexSegmentEdit )
387  pin = NULL;
388  }
389  }
390 
391  // if not editing a wire, search for pins first, in order to start a wire draw, if not a pin hit ....
392  if( pin )
393  {
394  // wire drawing mode
395  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
396  m_mode = mode_drawwire;
397  m_modehit = pin;
398  }
399  else
400  {
401  if( hit->GetDraggable() )
402  {
403  if ( hit->GetSelected() )
404  {
405  m_modehit = hit;
406  if ( event.ControlDown() && event.ShiftDown() )
407  {
408  m_mode = mode_copymulti;
409  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Copy ) );
410  }
411  else //no shift no control
412  {
413  m_mode = mode_dragmulti;
414  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
415  }
416  }
417  else
418  {
419  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
420  m_mode = mode_select;
421  m_modehit = hit;
422  }
423  }
424  else
425  {
426  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
427  m_mode = mode_select;
428  m_modehit = hit;
429  }
430  }
431  }
432  }
433  else
434  {
435  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
436  m_mode = mode_select;
437  m_modehit = hit;
438  }
439  }
440  event.Skip();
441  }
442  else if( event.LeftDown() && !m_toolBusy )
443  {
444  m_dragStarted = false;
445  m_xprev = m_x;
446  m_yprev = m_y;
447  m_dragstartx = m_x;
448  m_dragstarty = m_y;
449 
450  if( !m_modehit )
451  {
452  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
453  m_mode = mode_select;
454  event.Skip();
455  m_toolBusy = false;
456  return;
457  }
458 
459  switch( m_mode )
460  {
461  case mode_cntrlselect:
462  DeselectAll();
463  m_toolBusy = true;
464  break;
465  case mode_select:
466  m_toolBusy = true;
467  break;
468  case mode_move_pin:
469  PushMovePinTool( m_modehit );
470  event.Skip();
471  break;
472  case mode_drawwire:
473  PushDrawWireTool( m_modehit );
474  event.Skip();
475  break;
476  case mode_editwire_vertex:
477  PushEditWireVertexTool( m_modehit, m_modehitinfo.m_index );
478  event.Skip();
479  break;
480  case mode_editwire_segmenthorizontal:
481  PushEditWireSegmentHorizontalTool( m_modehit, m_modehitinfo.m_index );
482  event.Skip();
483  break;
484  case mode_editwire_segmentvertical:
485  PushEditWireSegmentVerticalTool( m_modehit, m_modehitinfo.m_index );
486  event.Skip();
487  break;
488  case mode_editwire_segmentinsert:
489  PushEditWireSegmentInsertTool( m_modehit, m_modehitinfo.m_index );
490  event.Skip();
491  break;
492  case mode_editwire_segment:
493  PushEditSegmentTool( m_modehit, m_modehitinfo.m_index );
494  event.Skip();
495  break;
496  default:
497  // not know untill a drag started or not.
498  m_mode = mode_none;
499  m_toolBusy = true;
500  event.Skip();
501  }
502  }
503  else if( event.LeftUp() && m_toolBusy && m_dragStarted )
504  {
505  m_toolBusy = false;
506  m_dragStarted = false; //end of drag
507  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
508  }
509  else if( event.LeftUp() && m_toolBusy )
510  {
511  m_toolBusy = false;
512  m_dragStarted = false; //never started but still
513 
514  //reserve for double click if it happens
515  m_modehitLastSelectState = false;
516  if ( m_modehit )
517  m_modehitLastSelectState = m_modehit->GetSelected();
518 
519  if ( !event.ControlDown() && !event.ShiftDown() )
520  {
521  DeselectAll();
522  if ( m_modehit && m_modehit->GetSelectable() )
523  m_modehit->SetSelected( true );
524  }
525  else if ( event.ShiftDown() )
526  {
527  if ( m_modehit && m_modehit->GetSelectable() )
528  {
529  if ( m_modehit->IsSelected() )
530  m_modehit->SetSelected( false );
531  else
532  m_modehit->SetSelected( true );
533  }
534  }
535  else
536  {
537  if ( !m_modehit )
538  DeselectAll();
539  else
540  {
541  if ( m_modehit->GetSelected() )
542  {
543  if ( m_mode == mode_none && m_modehit->GetSelectable() )
544  m_modehit->SetSelected( ! m_modehit->GetSelected() );
545  }
546  else
547  {
548  if ( m_mode == mode_none && m_modehit->GetSelectable() )
549  {
551  if ( selected )
552  {
553  DeselectAll();
554  m_modehit->SetSelected( true );
555  }
556  else
557  {
558  m_modehit->SetSelected( true );
559  }
560  }
561  }
562  }
563  }
564  if ( m_modehit && m_modehit->GetSelected() )
565  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
566  else
567  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
568  }
569  else if( event.RightDown() && !GetBusy() )
570  {
571  PushZoomTool();
572  event.Skip();
573  }
574  else
575  {
576  event.Skip();
577  }
578 }
579 
#define wxDynamicCast(obj, className)
Define wxDynamicCast so that it will give a compiler error for unrelated types.
Definition: gen.h:75
void Render()
implement rendering
unsigned int m_index
For edge/vertex hits the index of the edge / vertex.
Definition: polyver.h:89
a2dCanvasObjectPtr m_parentobject
( if needed ) parent a2dCanvasObject relative to which the tool actions take place.
Definition: tools.h:854
bool m_dragStarted
used to indicate that a first drag event has arrived.
Definition: sttool.h:374
The a2dBaseTool is used to derive tools from that are controlled by.
Definition: tools.h:379
no special options
Definition: canobj.h:79
virtual void DoStopTool(bool abort)
to do tool specific stuff to stop a tool. Called from StopTool().
Definition: mastertool.cpp:900
int m_x
x of mouse in device
Definition: sttool.h:352
double GetHitMargin()
Definition: tools.cpp:983
a2dPin is used in a2dCanvasObject to add pins to it.
Definition: canpin.h:233
stack based tools for drawing and editing in a faster manner, but with less document feedback...
generate pins, given Connect/wire pinclass
Definition: connectgen.h:48
a2dDrawingPart * GetDrawingPart()
Access to the tool controllers drawer.
Definition: tools.h:632
int m_dragstarty
y of mouse in device at start drag
Definition: sttool.h:371
a2dStToolContr * m_stcontroller
controller for canvas
Definition: sttool.h:391
a2dDrawing * GetDrawing()
Returns a pointer to the drawing.
Definition: tools.cpp:969
bool m_active
tool is operational
Definition: tools.h:777
int m_dragstartx
x of mouse in device at start drag
Definition: sttool.h:369
double m_ywprev
y world coordinates old or new value of mouse
Definition: sttool.h:366
float m_distance
For margin hits, the distance from the stroke center in fractions of the margin.
Definition: polyver.h:93
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
a2dCanvasObjectList * GetChildObjectList()
get the list where the child objects are stored in.
Definition: canobj.cpp:2551
bool GetSelected() const
is the object selected flag set
Definition: canobj.h:1603
void SetSelected(bool selected)
Set the object selected flag if allowed.
Definition: canobj.h:1620
master tool using tags to groups object
a2dWirePolylineL is a polyline that adjusts itself when the objects it connects move ...
Definition: wire.h:42
The a2dStToolContr is a Tool Controller specialized for working with a2dCanvasView.
Definition: sttool.h:485
static const a2dCanvasObjectFlagsMask SELECTABLE
Definition: candefs.h:182
a2dCanvasObject * GetShowObject() const
return pointer of then currently shown object on the drawer.
Definition: drawer.h:680
int m_yprev
previous y of mouse in device
Definition: sttool.h:360
if set, respect layer order, hit testing is done per layer from the top.
Definition: canobj.h:82
static const a2dCanvasObjectFlagsMask SELECTED
Definition: candefs.h:180
bool IsSelected() const
Is the object selected flag set.
Definition: canobj.h:1610
Master tool for objects graphics selecting and dragging.
a2dCanvasObject * ChildIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent, bool filterSelectableLayers=false)
Do hittest on children.
Definition: canobj.cpp:3289
bool IsTemporaryPin() const
return true if this pin is a temporary pin
Definition: canpin.h:433
double m_xwprev
x world coordinates old or new value of mouse
Definition: sttool.h:363
common stuff for several master tools
Definition: mastertool.h:167
virtual void AbortBusyMode()
Called when the user aborts editing a distinct object */.
Definition: sttool.cpp:1178
while iterating a a2dCanvasDocument, this holds the context.
Definition: canobj.h:3212
struct for how a single object on one layer was hit
Definition: polyver.h:38
a2dConnectionGenerator * GetConnectionGenerator() const
Get class for generating new connection objects between object and pins.
Definition: canglob.h:601
static const a2dCanvasObjectFlagsMask VISIBLE
Definition: candefs.h:186
int m_y
y of mouse in device
Definition: sttool.h:354
a2dBaseTool * GetFirstTool() const
get currently used eventhandler (always the first in the list)
Definition: tools.cpp:91
a2dCanvasObject * Find(a2dCanvasObject *obj) const
return the object if it is part of the list
Definition: objlist.cpp:553
bool GetSelectable() const
is the object selectable flag set
Definition: canobj.h:1648
void AbortBusyMode()
Called when the user aborts editing a distinct object */.
virtual void SetPinsToBeginState(a2dCanvasObject *root, a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::VISIBLE)
set begin state of pins, before a tools starts asking feedback or after tool is finsihed ...
static a2dPinClass * Any
used to ask for a new default pin on an object.
Definition: canpin.h:763
a2dCanvasGlobal * a2dCanvasGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: canglob.cpp:1234
all headers of the canvas module
filter on this layer and mask.
Definition: canobj.h:2780
void MouseToToolWorld(int x, int y, double &xWorldLocal, double &yWorldLocal)
calculate world coordinates from devide coordinates
Definition: sttool.cpp:1622
bool GetBusy()
Check if the tool is busy editing a distinct object */.
Definition: tools.h:513
a2dCanvasObject * GetParent() const
get parent object of the pin
Definition: canpin.h:295
int m_xprev
previous x of mouse in device
Definition: sttool.h:357
stack based tools controller and tools for drawing and editing.
bool GetDraggable() const
get if the object can be dragged
Definition: canobj.h:1676
structure to give as parameter to member functions of a2dCanvasObject
Definition: canobj.h:252
void DoStopTool(bool abort)
to do tool specific stuff to stop a tool. Called from StopTool().
mastertoolgroups2.cpp Source File -- Sun Oct 12 2014 17:04:22 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation