~vbursian/research-assistant/intervers

« back to all changes in this revision

Viewing changes to RAGUI/Chart.cpp

  • Committer: Viktor Bursian
  • Date: 2013-06-06 15:10:08 UTC
  • Revision ID: vbursian@gmail.com-20130606151008-6641eh62f0lgx8jt
Tags: version_0.3.0
version 0.3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
                     Viktor.Bursian@mail.ioffe.ru
8
8
*///////////////////////////////////////////////////////////////////////////////
9
9
#include "Chart.h"
 
10
#include "SymbolsGUI.h"
 
11
#include "StringsAndQStrings.h"
 
12
#include "NetOps.h"
 
13
#include "DlgEditScales.h"
 
14
#include "Log.h"
10
15
#include "Trace.h"
11
 
#include "GeneralGUI.h"
12
 
#include "SetScalesDlg.h"
13
16
#include <algorithm>
14
17
#include <QPainter>
15
18
#include <QApplication>
29
32
QCursor *               sChartViewport::ZoomingCursor = NULL;
30
33
QCursor *               sChartViewport::ShiftingCursor = NULL;
31
34
sNetViewMenuGenerators  sChartViewport::MenuGenerators;
32
 
pfChartItemDrawProc     sChartViewport::DrawProc;
 
35
list<pcfDrawProc>       sChartViewport::DrawProcCollection;
33
36
 
34
37
//--------------------------------------------------------------- sChartItem ---
35
38
 
38
41
//};
39
42
 
40
43
 
41
 
sChartItem::sChartItem (psNetViewport               viewport
42
 
                       ,sNet2TreeEvolution::psItem  tree_item
43
 
                       ,pfChartItemDrawProc         draw_proc)
44
 
    :sNetViewItem(viewport,tree_item)
45
 
    ,Draw(draw_proc)
46
 
{
47
 
};
 
44
//sChartItem::sChartItem (psNetViewport               viewport
 
45
//                       ,sNet2TreeEvolution::psItem  tree_item
 
46
//                       ,pfChartItemDrawProc         draw_proc)
 
47
//    :sNetViewItem(viewport,tree_item)
 
48
//    ,Draw(draw_proc)
 
49
//{
 
50
//};
48
51
 
49
52
//--------------------------------------------------------------- sChartMenu ---
50
53
 
60
63
////  psChart  Chart(dynamic_cast<psChart>(viewport->parent()));
61
64
//};
62
65
 
 
66
//-------------------------------------------------------------- sChartScales ---
 
67
 
 
68
void  sChartScales::RestoreSettings (sCluster::sPtr  C)
 
69
{
 
70
  if( C.IsCorrect() ){
 
71
    sTextNode::sPtr           V;
 
72
    sPhysRangeNode::sPtr      R;
 
73
    V=C->GetAttr("ScaleX.Variable");
 
74
    if( V.IsCorrect() )  X.Name=V->Value();
 
75
    V=C->GetAttr("ScaleY.Variable");
 
76
    if( V.IsCorrect() )  Y.Name=V->Value();
 
77
 
 
78
    R=C->GetAttr("ScaleX.Range");
 
79
    if( R.IsCorrect() )  X.Range=(sPhysRange)(*R);
 
80
    R=C->GetAttr("ScaleY.Range");
 
81
    if( R.IsCorrect() )  Y.Range=(sPhysRange)(*R);
 
82
  };
 
83
};
 
84
 
 
85
 
 
86
void  sChartScales::StoreSettings (sCluster::sPtr  C) const
 
87
{
 
88
  if( C.IsCorrect() ){
 
89
    C   << attr("ScaleX.Variable",X.Name)
 
90
        << attr("ScaleX.Range",X.Range)
 
91
        << attr("ScaleY.Variable",Y.Name)
 
92
        << attr("ScaleY.Range",Y.Range);
 
93
  };
 
94
};
 
95
 
63
96
//----------------------------------------------------------------- sMargins ---
64
97
 
65
98
sMargins::sMargins (int top ,int  bottom ,int  left ,int right)
95
128
 
96
129
//--------------------------------------------------------------- sAxis ---
97
130
 
98
 
sAxis::sAxis ()
99
 
    :Range(0.0,9.0)
 
131
sAxis::sAxis (bool  upside_down)
 
132
    :sScale(upside_down)
 
133
    ,Variable()
100
134
    ,MultiplierExponent(0)
101
135
    ,Multiplier(1)
102
136
    ,Shift(0.0)
103
 
    ,PenWidth(1)
 
137
    ,LabelsArranged(false)
 
138
    ,LabelsOverlap(false)
104
139
{
 
140
  SetPenWidth(1);
105
141
  Title.setDocumentMargin(0);
106
142
  MinorTicks.Length=(MajorTicks.Length+1) / 2;
 
143
  SetRange(sPhysRange(0,10,sUnits()));
 
144
};
 
145
 
 
146
 
 
147
void  sAxis::SetPenWidth (int  width)
 
148
{
 
149
  PenWidth = width;
 
150
  SetOffset((PenWidth+1)/2);
107
151
};
108
152
 
109
153
 
110
154
int  sAxis::Value2Offset (real value)
111
155
{
112
 
  return ( (Range.To > Range.From)
113
 
         ? Round((value-Range.From)/(Range.To-Range.From)*NominalSize)
114
 
         : 0
115
 
         );
 
156
  try{
 
157
    return Round((value-Range().From)/(Range().To-Range().From)*Size());
 
158
  }catch(...){
 
159
    return 0;
 
160
  };
116
161
};
117
162
 
118
163
 
119
164
void  sAxis::Arrange (const QFontMetrics &  font_metrics)
120
165
{
121
 
  bool                        LabelsOverlap;
122
 
 
123
 
  Error=false;
124
166
  MultiplierExponent=0;
125
 
  MultiplierExponent=3*Round(log10( max(fabs(Range.From),fabs(Range.To))
 
167
  MultiplierExponent=3*Round(log10( max(fabs(Range().From),fabs(Range().To))
126
168
                                  )/3.0-0.5);
127
169
  Multiplier=power10(MultiplierExponent);
128
170
  MajorTicks.Interval
129
 
      = Multiplier * power10(Round(log10(
130
 
                (Range.To-Range.From)/Multiplier/Labels.MaxAmount)-1.5)
131
 
                                         );
 
171
      = Multiplier * power10(Round( -1.0 + log10(
 
172
                   (Range().To-Range().From)/Multiplier/Labels.MaxAmount
 
173
                                                ) ));
132
174
  MinorTicks.Interval=MajorTicks.Interval / 10;
133
 
  ArrangeLabels(font_metrics,LabelsOverlap);
134
 
  if( LabelsOverlap || (Labels.List.size() > Labels.MaxAmount) ){
 
175
  ;
 
176
  if( ArrangeLabels(font_metrics) ){
 
177
    RANet::Log.Put(sLog::Debug,"Graph"
 
178
        ,sString("sAxis::Arrange: success in step #")<<1 );
 
179
  }else{
135
180
    MajorTicks.Interval*=2.0;
136
181
    MinorTicks.Interval=MajorTicks.Interval / 2;
137
 
    ArrangeLabels(font_metrics,LabelsOverlap);
138
 
    if( LabelsOverlap || (Labels.List.size() > Labels.MaxAmount) ){
 
182
    if( ArrangeLabels(font_metrics) ){
 
183
      RANet::Log.Put(sLog::Debug,"Graph"
 
184
          ,sString("sAxis::Arrange: success in step #")<<2 );
 
185
    }else{
139
186
      MajorTicks.Interval*=2.5;
140
187
      MinorTicks.Interval=MajorTicks.Interval / 5;
141
 
      ArrangeLabels(font_metrics,LabelsOverlap);
142
 
      if( LabelsOverlap || (Labels.List.size() > Labels.MaxAmount) ){
 
188
      if( ArrangeLabels(font_metrics) ){
 
189
        RANet::Log.Put(sLog::Debug,"Graph"
 
190
            ,sString("sAxis::Arrange: success in step #")<<3 );
 
191
      }else{
143
192
        MajorTicks.Interval*=2.0;
144
193
        MinorTicks.Interval=MajorTicks.Interval / 10;
145
 
        ArrangeLabels(font_metrics,LabelsOverlap);
146
 
        if( LabelsOverlap || (Labels.List.size() > Labels.MaxAmount) ){
 
194
        if( ArrangeLabels(font_metrics) ){
 
195
          RANet::Log.Put(sLog::Debug,"Graph"
 
196
              ,sString("sAxis::Arrange: success in step #")<<4 );
 
197
        }else{
147
198
          MajorTicks.Interval*=2.0;
148
199
          MinorTicks.Interval=MajorTicks.Interval / 2;
149
 
          ArrangeLabels(font_metrics,LabelsOverlap);
150
 
          if( LabelsOverlap || (Labels.List.size() > Labels.MaxAmount) ){
 
200
          if( ArrangeLabels(font_metrics) ){
 
201
            RANet::Log.Put(sLog::Debug,"Graph"
 
202
                ,sString("sAxis::Arrange: success in step #")<<5 );
 
203
          }else{
151
204
            MajorTicks.Interval*=2.5;
152
205
            MinorTicks.Interval=MajorTicks.Interval / 5;
153
 
            ArrangeLabels(font_metrics,LabelsOverlap);
154
 
            if( LabelsOverlap || (Labels.List.size() > Labels.MaxAmount) ){
 
206
            if( ArrangeLabels(font_metrics) ){
 
207
              RANet::Log.Put(sLog::Debug,"Graph"
 
208
                  ,sString("sAxis::Arrange: success in step #")<<6 );
 
209
            }else{
155
210
              MajorTicks.Interval*=2.0;
156
211
              MinorTicks.Interval=MajorTicks.Interval / 10;
157
 
              ArrangeLabels(font_metrics,LabelsOverlap);
158
 
              if( LabelsOverlap || (Labels.List.size() > Labels.MaxAmount) ){
 
212
              if( ArrangeLabels(font_metrics) ){
 
213
                RANet::Log.Put(sLog::Debug,"Graph"
 
214
                    ,sString("sAxis::Arrange: success in step #")<<7 );
 
215
              }else{
159
216
                MajorTicks.Interval*=2.0;
160
217
                MinorTicks.Interval=MajorTicks.Interval / 2;
161
 
                ArrangeLabels(font_metrics,LabelsOverlap);
162
 
                if( LabelsOverlap || (Labels.List.size() > Labels.MaxAmount) ){
 
218
                if( ArrangeLabels(font_metrics) ){
 
219
                  RANet::Log.Put(sLog::Debug,"Graph"
 
220
                      ,sString("sAxis::Arrange: success in step #")<<8 );
 
221
                }else{
163
222
                  MajorTicks.Interval*=2.5;
164
223
                  MinorTicks.Interval=MajorTicks.Interval / 5;
165
 
                  ArrangeLabels(font_metrics,LabelsOverlap);
166
 
                  if( LabelsOverlap || (Labels.List.size() > Labels.MaxAmount) ){
167
 
                    TRACE("sAxis::Arrange - no success !!!!!!!!!!!!!!!!!!!!!!");
168
 
                    Error=true;
 
224
                  if( ArrangeLabels(font_metrics) ){
 
225
                    RANet::Log.Put(sLog::Debug,"Graph"
 
226
                        ,sString("sAxis::Arrange: success in step #")<<9 );
169
227
                  }else{
170
 
//                    TRACE("sAxis::Arrange - success in eigth try");
 
228
                    RANet::Log.Put(sLog::Debug,"Graph"
 
229
                        ,sString("sAxis::Arrange: no success !!!!!!!!!!!!!!!!!"));
171
230
                  };
172
 
                }else{
173
 
//                  TRACE("sAxis::Arrange - success in seventh try");
174
231
                };
175
 
              }else{
176
 
//                TRACE("sAxis::Arrange - success in sixth try");
177
232
              };
178
 
            }else{
179
 
//              TRACE("sAxis::Arrange - success in fifth try");
180
233
            };
181
 
          }else{
182
 
//            TRACE("sAxis::Arrange - success in fourth try");
183
234
          };
184
 
        }else{
185
 
          TRACE("sAxis::Arrange - success in third try");
186
235
        };
187
 
      }else{
188
 
        TRACE("sAxis::Arrange - success in second try");
189
236
      };
190
 
    }else{
191
 
      TRACE("sAxis::Arrange - success in first try");
192
237
    };
193
238
  };
194
 
  MinorTicks.Start=Round(Range.From/MinorTicks.Interval+0.499)*MinorTicks.Interval;
 
239
  if(MultiplierExponent)
 
240
    RANet::Log.Put(sLog::Debug,"Graph"
 
241
        ,sString(" MultiplierExponent=")<<MultiplierExponent
 
242
        );
 
243
//  RANet::Log.Put(sLog::Debug,"Graph"
 
244
//      ,sString("sAxis::Arrange: LabelsArranged=")+(LabelsArranged ? "Y" : "N")
 
245
//      +sString(" LabelsOverlap=")+(LabelsOverlap ? "Y" : "N")
 
246
//      );
195
247
};
196
248
 
197
249
 
200
252
  const int                   ShiftQuantumLog = 5;
201
253
                              /*!< =lg(ShiftQuantum/MinorTicks.Interval) */
202
254
  real                        tick;
 
255
  int                         NumOfMajorTicks = 0;
203
256
  int                         digits = 0;
204
257
  sString                     label_text;
205
258
  QString                     LabelText;
206
259
  real                        ShiftQuantum;
207
 
  real                        MidScale = (Range.From+Range.To)/2.0;
 
260
  real                        MidScale = (Range().From+Range().To)/2.0;
 
261
 
 
262
  LabelsArranged=false;
208
263
  ShiftQuantum=MinorTicks.Interval*power10(ShiftQuantumLog);
209
 
  MultiplierExponent=3*Round(log10( max(fabs(Range.From),fabs(Range.To))
 
264
  MultiplierExponent=3*Round(log10( max(fabs(Range().From),fabs(Range().To))
210
265
                                  )/3.0-0.5);
211
266
  Multiplier=power10(MultiplierExponent);
212
 
  MajorTicks.Start=Round(Range.From/MajorTicks.Interval+0.499)*MajorTicks.Interval;
 
267
  MajorTicks.Start=Round(Range().From/MajorTicks.Interval+0.499)*MajorTicks.Interval;
 
268
  MinorTicks.Start=MajorTicks.Start - MajorTicks.Interval;
213
269
  if( MidScale > 0.0 ){
214
270
    Shift=Round(floor(MidScale/ShiftQuantum))*ShiftQuantum;
215
271
  }else{
224
280
    digits=-Round(log10(MajorTicks.Interval/Multiplier)-0.499);
225
281
  };
226
282
  tick=MajorTicks.Start;
227
 
  while( tick < Range.To + PixelValue()){   /*! @todo{bug} Infinite cycling if Interval is too small */
 
283
  while( tick < Range().To + PixelValue() ){
228
284
    LabelText.setNum(double((tick-Shift)/Multiplier),'f',digits);
229
285
    Labels.List.push_back(sLabel(LabelText));
230
286
    tick+=MajorTicks.Interval;
 
287
    NumOfMajorTicks++;
 
288
    if( NumOfMajorTicks > 1000*(int)Labels.MaxAmount ){
 
289
      RANet::Log.Put(sLog::Debug,"Graph"
 
290
          ,sString("cycling in sAxis::PrearrangeLabels: ")+Variable
 
291
          +"  Range().From="+sString::FromReal(Range().From,12)
 
292
          +"  Range().To="+sString::FromReal(Range().To,12)
 
293
          +"  MajorTicks.Interval="+sString::FromReal(MajorTicks.Interval,12)
 
294
          +"  MajorTicks.Start="+sString::FromReal(MajorTicks.Start,12)
 
295
//          +"  ="+sString::FromReal()
 
296
          );
 
297
      return;
 
298
    };
231
299
  };
 
300
  LabelsArranged = ! Labels.List.empty()
 
301
                && (Labels.List.size() <= Labels.MaxAmount);
 
302
//  RANet::Log.Put(sLog::Debug,"Graph",sString("Prearranged ")+Variable
 
303
//      +"  Labels.List.size()="+sString::FromInteger(Labels.List.size())
 
304
//      +"  MajorTicks.Start="+sString::FromReal(MajorTicks.Start,15)
 
305
//      +"  MinorTicks.Start="+sString::FromReal(MinorTicks.Start,15)
 
306
//      +"  MajorTicks.Interval="+sString::FromReal(MajorTicks.Interval,15)
 
307
//      +"  MinorTicks.Interval="+sString::FromReal(MinorTicks.Interval,15)
 
308
//      +"  LabelsArranged="+sString::FromInteger(LabelsArranged)
 
309
//      );
232
310
};
233
311
 
234
312
 
235
313
QString  sAxis::TitleText ()
236
314
{
237
 
  //+-×
 
315
  sPhysValue            U(Unit());
238
316
  int                   Exp=MultiplierExponent;
 
317
 
 
318
  U << Exp;
 
319
  Exp = 0;
 
320
 
239
321
  sString               ExpText;
240
 
  sString               UnitsText;
 
322
  sString               UnitsText(U.Text(HTML,Laconic));
241
323
  sString               ShiftText;
242
 
  /*! @todo{Units} make Prefix and Exp (and Shift?) specific for scale units */
243
 
//  UnitsText=sMetricPrefix::Symbol(MultiplierExponent) + "<i>1</i>";
244
 
//  Exp=0;
245
 
  /*! @todo{Units} set Variable for scales */
246
 
  Variable="";
 
324
  sString               VarText(Variable);
 
325
  if( ! Unit().IsPowerOfTen() ){
 
326
    RANet::Log.Put(sLog::Debug,"Graph",sString("TitleText: not a power of ten: ")+Unit().Text());
 
327
  };
247
328
  //---------
 
329
  if( VarText.Empty() ){
 
330
    VarText = sString("<i>") + VarText + "</i>";
 
331
  };
248
332
  if( Shift > fabs(PixelValue()) ){
249
333
    if( Variable.Empty() ){
250
334
      ShiftText=" + ";
263
347
    };
264
348
  };
265
349
  if( Variable.Empty() && UnitsText.Empty() ){
266
 
    if( Exp != 0 )  ((ExpText = "×10<sup>") << Exp ) += "</sup> ";
267
 
    return sString2QString( ExpText  + ShiftText );
 
350
    if( Exp != 0 )
 
351
      (((ExpText = Symbol::Multiplication) += "10<sup>") << Exp) += "</sup> ";
 
352
    return ToQString( ExpText  + ShiftText );
268
353
  }else if( Variable.Empty() ){
269
 
    /*! @todo{Units} test and review this option */
270
 
    if( Exp != 0 )  ((ExpText = "×10<sup>") << Exp ) += "</sup> ";
271
 
    return sString2QString( ExpText  + ShiftText + " [ " + UnitsText + " ]" );
 
354
    /*! @todo{PhysValues} test and review this option */
 
355
    if( Exp != 0 )
 
356
      (((ExpText = Symbol::Multiplication) += "10<sup>") << Exp ) += "</sup> ";
 
357
    return ToQString( ExpText  + ShiftText + " [ " + UnitsText + " ]" );
272
358
  }else{
273
359
    if( Exp != 0 )  ((ExpText = "10<sup>") << (Exp) ) += "</sup> ";
274
 
    return sString2QString( Variable + ShiftText
 
360
    return ToQString( VarText + ShiftText
275
361
                          + " [ " + ExpText + UnitsText + " ]" );
276
362
  };
277
363
};
279
365
//--------------------------------------------------------------- sX_Axis ---
280
366
 
281
367
 
282
 
void  sX_Axis::ArrangeLabels (const QFontMetrics &  font_metrics
283
 
                             ,bool &                LabelsOverlap)
 
368
bool  sX_Axis::ArrangeLabels (const QFontMetrics &  font_metrics)
284
369
{
285
370
  real                        tick_value;
286
371
  int                         tick_pos;
316
401
    tick_value+=MajorTicks.Interval;
317
402
  };
318
403
  Title.setHtml(TitleText());
319
 
  TitleArea = QRect(Origin.x() + NominalSize/2 - Title.size().width()/2
 
404
  TitleArea = QRect(Origin.x() + Size()/2 - Title.size().width()/2
320
405
                   ,LabelsArea.bottom()
321
406
                   ,Title.size().width()
322
407
                   ,Title.size().height() );
 
408
//  RANet::Log.Put(sLog::Debug,"Graph",sString("ArrangeLabels result ")+Variable
 
409
//      +"  Labels.List.size()="+sString::FromInteger(Labels.List.size())
 
410
//      +"  LabelsArranged="+sString::FromInteger(LabelsArranged)
 
411
//      +"  LabelsOverlap="+sString::FromInteger(LabelsOverlap)
 
412
//      );
 
413
  return LabelsArranged && ! LabelsOverlap;
323
414
};
324
415
 
325
416
 
326
417
void  sX_Axis::Draw (QPainter *  painter)
327
418
{
 
419
//  RANet::Log.Put(sLog::Debug,"Graph","-------------------X-drawing...");
328
420
  real                        tick_value;
329
421
  int                         tick_pos;
330
422
  QPen                        Pen=painter->pen();
332
424
  Pen.setWidth(PenWidth);
333
425
  painter->setPen(Pen);
334
426
  painter->drawLine( Origin.x()        , Origin.y()
335
 
                   , Origin.x()+NominalSize , Origin.y());
 
427
                   , Origin.x()+Size() , Origin.y());
336
428
  painter->drawLine( OppositeOrigin.x()        , OppositeOrigin.y()
337
 
                   , OppositeOrigin.x()+NominalSize , OppositeOrigin.y() );
338
 
  tick_value=MinorTicks.Start;
339
 
  while( tick_value < Range.To + PixelValue() ){
340
 
    tick_pos=Origin.x()+Value2Offset(tick_value);
341
 
    painter->drawLine(tick_pos ,Origin.y()
342
 
                     ,tick_pos ,Origin.y() + MinorTicks.Length);
343
 
    painter->drawLine(tick_pos ,OppositeOrigin.y()
344
 
                     ,tick_pos ,OppositeOrigin.y() - MinorTicks.Length);
345
 
    tick_value+=MinorTicks.Interval;
346
 
  };
347
 
  tick_value=MajorTicks.Start;
348
 
  while( tick_value < Range.To + PixelValue() ){
349
 
    tick_pos=Origin.x()+Value2Offset(tick_value);
350
 
    painter->drawLine(tick_pos ,Origin.y()
351
 
                     ,tick_pos ,Origin.y() + MajorTicks.Length);
352
 
    painter->drawLine(tick_pos ,OppositeOrigin.y()
353
 
                     ,tick_pos ,OppositeOrigin.y() - MajorTicks.Length);
354
 
    tick_value+=MajorTicks.Interval;
355
 
  };
 
429
                   , OppositeOrigin.x()+Size() , OppositeOrigin.y() );
 
430
  if( LabelsArranged ){
 
431
    tick_value=MinorTicks.Start;
 
432
    while( tick_value < Range().To + PixelValue() ){
 
433
//      RANet::Log.Put(sLog::Debug,"Graph",sString("min tick ")+sString::FromReal(tick_value,15));
 
434
      if( tick_value >= Range().From ){
 
435
        tick_pos=Origin.x()+Value2Offset(tick_value);
 
436
        painter->drawLine(tick_pos ,Origin.y()
 
437
                         ,tick_pos ,Origin.y() + MinorTicks.Length);
 
438
        painter->drawLine(tick_pos ,OppositeOrigin.y()
 
439
                         ,tick_pos ,OppositeOrigin.y() - MinorTicks.Length);
 
440
      };
 
441
      tick_value+=MinorTicks.Interval;
 
442
    };
 
443
//    RANet::Log.Put(sLog::Debug,"Graph",sString("min ticks done "));
 
444
    tick_value=MajorTicks.Start;
 
445
    while( tick_value < Range().To + PixelValue() ){
 
446
      tick_pos=Origin.x()+Value2Offset(tick_value);
 
447
      painter->drawLine(tick_pos ,Origin.y()
 
448
                       ,tick_pos ,Origin.y() + MajorTicks.Length);
 
449
      painter->drawLine(tick_pos ,OppositeOrigin.y()
 
450
                       ,tick_pos ,OppositeOrigin.y() - MajorTicks.Length);
 
451
      tick_value+=MajorTicks.Interval;
 
452
    };
 
453
  };
 
454
//  RANet::Log.Put(sLog::Debug,"Graph",sString("ticks done "));
356
455
  painter->restore();
357
 
  for( list<sLabel>::iterator  label_index = Labels.List.begin() ;
358
 
                               label_index != Labels.List.end() ;
359
 
                               label_index++ ){
360
 
    painter->drawText(label_index->Rect
361
 
                     ,Qt::AlignHCenter|Qt::AlignTop
362
 
                     ,label_index->Text);
 
456
  if( LabelsArranged && ! LabelsOverlap ){
 
457
    for( list<sLabel>::iterator  label_index = Labels.List.begin() ;
 
458
                                 label_index != Labels.List.end() ;
 
459
                                 label_index++ ){
 
460
      painter->drawText(label_index->Rect
 
461
                       ,Qt::AlignHCenter|Qt::AlignTop
 
462
                       ,label_index->Text);
 
463
    };
363
464
  };
364
465
  painter->save();
365
466
  painter->translate( TitleArea.topLeft() );
366
467
  Title.drawContents(painter);
367
468
  painter->restore();
 
469
//  RANet::Log.Put(sLog::Debug,"Graph","-------------------X-drawn----------------");
368
470
};
369
471
 
370
472
//--------------------------------------------------------------- sY_Axis ---
371
473
 
372
474
 
373
 
void  sY_Axis::ArrangeLabels (const QFontMetrics &  font_metrics
374
 
                             ,bool &                LabelsOverlap)
 
475
bool  sY_Axis::ArrangeLabels (const QFontMetrics &  font_metrics)
375
476
{
376
477
  real                        tick_value;
377
478
  int                         tick_pos;
406
507
  };
407
508
  Title.setHtml(TitleText());
408
509
  TitleArea = QRect(2
409
 
                   ,Origin.y() - NominalSize/2 + Title.size().width()/2
 
510
                   ,Origin.y() - Size()/2 + Title.size().width()/2
410
511
                   ,Title.size().height()
411
512
                   ,Title.size().width() );
 
513
//  RANet::Log.Put(sLog::Debug,"Graph",sString("ArrangeLabels result ")+Variable
 
514
//      +"  Labels.List.size()="+sString::FromInteger(Labels.List.size())
 
515
//      +"  LabelsArranged="+sString::FromInteger(LabelsArranged)
 
516
//      +"  LabelsOverlap="+sString::FromInteger(LabelsOverlap)
 
517
//      );
 
518
  return LabelsArranged && ! LabelsOverlap;
412
519
};
413
520
 
414
521
 
415
522
void  sY_Axis::Draw (QPainter *  painter)
416
523
{
 
524
//  RANet::Log.Put(sLog::Debug,"Graph","-------------------Y-drawing...");
417
525
  real                        tick_value;
418
526
  int                         tick_pos;
419
527
  QPen                        Pen=painter->pen();
421
529
  Pen.setWidth(PenWidth);
422
530
  painter->setPen(Pen);
423
531
  painter->drawLine( Origin.x() , Origin.y()
424
 
                   , Origin.x() , Origin.y()-NominalSize );
 
532
                   , Origin.x() , Origin.y()-Size() );
425
533
  painter->drawLine( OppositeOrigin.x() , OppositeOrigin.y()
426
 
                   , OppositeOrigin.x() , OppositeOrigin.y()-NominalSize );
427
 
  tick_value=MinorTicks.Start;
428
 
  while( tick_value < Range.To + PixelValue() ){
429
 
    tick_pos=Origin.y()-Value2Offset(tick_value);
430
 
    painter->drawLine(Origin.x()                             ,tick_pos
431
 
                     ,Origin.x() - MinorTicks.Length         ,tick_pos);
432
 
    painter->drawLine(OppositeOrigin.x()                     ,tick_pos
433
 
                     ,OppositeOrigin.x() + MinorTicks.Length ,tick_pos);
434
 
    tick_value+=MinorTicks.Interval;
435
 
  };
436
 
  tick_value=MajorTicks.Start;
437
 
  while( tick_value < Range.To + PixelValue() ){
438
 
    tick_pos=Origin.y()-Value2Offset(tick_value);
439
 
    painter->drawLine(Origin.x()                             ,tick_pos
440
 
                     ,Origin.x() - MajorTicks.Length         ,tick_pos);
441
 
    painter->drawLine(OppositeOrigin.x()                     ,tick_pos
442
 
                     ,OppositeOrigin.x() + MajorTicks.Length ,tick_pos);
443
 
    tick_value+=MajorTicks.Interval;
 
534
                   , OppositeOrigin.x() , OppositeOrigin.y()-Size() );
 
535
  if( LabelsArranged ){
 
536
    tick_value=MinorTicks.Start;
 
537
    while( tick_value < Range().To + PixelValue() ){
 
538
      if( tick_value >= Range().From ){
 
539
        tick_pos=Origin.y()-Value2Offset(tick_value);
 
540
        painter->drawLine(Origin.x()                             ,tick_pos
 
541
                         ,Origin.x() - MinorTicks.Length         ,tick_pos);
 
542
        painter->drawLine(OppositeOrigin.x()                     ,tick_pos
 
543
                         ,OppositeOrigin.x() + MinorTicks.Length ,tick_pos);
 
544
      };
 
545
      tick_value+=MinorTicks.Interval;
 
546
    };
 
547
    tick_value=MajorTicks.Start;
 
548
    while( tick_value < Range().To + PixelValue() ){
 
549
      tick_pos=Origin.y()-Value2Offset(tick_value);
 
550
      painter->drawLine(Origin.x()                             ,tick_pos
 
551
                       ,Origin.x() - MajorTicks.Length         ,tick_pos);
 
552
      painter->drawLine(OppositeOrigin.x()                     ,tick_pos
 
553
                       ,OppositeOrigin.x() + MajorTicks.Length ,tick_pos);
 
554
      tick_value+=MajorTicks.Interval;
 
555
    };
444
556
  };
445
557
  painter->restore();
446
 
  for( list<sLabel>::iterator  label_index = Labels.List.begin() ;
447
 
                               label_index != Labels.List.end() ;
448
 
                               label_index++ ){
449
 
    painter->drawText(label_index->Rect
450
 
                     ,Qt::AlignVCenter|Qt::AlignRight
451
 
                     ,label_index->Text);
 
558
  if( LabelsArranged && ! LabelsOverlap ){
 
559
    for( list<sLabel>::iterator  label_index = Labels.List.begin() ;
 
560
                                 label_index != Labels.List.end() ;
 
561
                                 label_index++ ){
 
562
      painter->drawText(label_index->Rect
 
563
                       ,Qt::AlignVCenter|Qt::AlignRight
 
564
                       ,label_index->Text);
 
565
    };
452
566
  };
453
567
  painter->save();
454
568
  painter->translate( TitleArea.topLeft() );
455
569
  painter->rotate(-90);
456
570
  Title.drawContents(painter);
457
571
  painter->restore();
 
572
//  RANet::Log.Put(sLog::Debug,"Graph","-------------------Y-drawn----------------");
458
573
};
459
574
 
460
575
//----------------------------------------------------------- sChartViewport ---
464
579
  Clear();
465
580
}
466
581
 
467
 
sChartViewport::sChartViewport(psNet2TreeEvolution  evolution
 
582
sChartViewport::sChartViewport(psX_Axis             x_axis
 
583
                              ,psY_Axis             y_axis
 
584
                              ,psNet2TreeEvolution  evolution
468
585
                              ,QWidget *            parent)
469
586
  :sNetViewport(evolution,parent)
 
587
  ,XAxis(x_axis)
 
588
  ,YAxis(y_axis)
470
589
  ,MouseOperationIsAboutToStart(false)
471
590
  ,MouseOperationStarted(false)
472
591
  ,DragIsAboutToStart(false)
490
609
  setMouseTracking(true);
491
610
  setCursor(*CrossHairCursor);
492
611
  setAcceptDrops(CurveDropsAreAllowed);
 
612
  connect(this,SIGNAL(CursorPositionChanged(QPoint))
 
613
         ,this,SLOT(OnCursorPositionChanged(QPoint)));
493
614
};
494
615
 
495
616
 
498
619
  Clear();
499
620
//  sNet2TreeEvolution::psItem  I = Evolution->FirstVisible();
500
621
//  while( I ){
501
 
//    s2DVisibleObject::sPtr    NodePtr(I->AttrValue());
 
622
//    sGraphObject::sPtr    NodePtr(I->AttrValue());
502
623
//    if( NodePtr.IsCorrect() ){
503
624
//      sCurve::sPtr              CurvePtr(NodePtr);
504
625
//      if( CurvePtr.IsCorrect() ){
516
637
 
517
638
void  sChartViewport::Clear ()
518
639
{
519
 
  psChartItem            I;
520
 
  while( ! Items.empty() ){
521
 
    I=Items.back();
522
 
    Items.pop_back();
523
 
    delete I;
524
 
  };
 
640
//  psChartItem            I;
 
641
//  while( ! Items.empty() ){
 
642
//    I=Items.back();
 
643
//    Items.pop_back();
 
644
//    delete I;
 
645
//  };
525
646
};
526
647
 
527
648
 
528
649
sNet2TreeEvolution::psItem  sChartViewport::FindTreeItemAt (const QPoint &  pos)
529
650
{
530
651
  int                         MinDist = 5;
531
 
  sPoint                      Pos = Offset2Value(pos);
 
652
  sIntPoint                   Pos(pos.x(),pos.y());
532
653
  sNet2TreeEvolution::psItem  ClosestItem = NULL;
533
654
  sNet2TreeEvolution::psItem  I = Evolution->FirstVisible();
534
655
  while( I ){
535
 
    sCurve::sPtr                CurvePtr(I->AttrValue());
536
 
    if( CurvePtr.IsCorrect() ){
537
 
      int  D = CurvePtr->Distance(Pos
538
 
                                 ,(TheScale.To.X-TheScale.From.X)
539
 
                                                 /NominalSize.width()
540
 
                                 ,(TheScale.To.Y-TheScale.From.Y)
541
 
                                                /NominalSize.height()
542
 
                                 );
 
656
    if( psGraphObject  O = dynamic_cast<psGraphObject>
 
657
                                           (I->AttrValue().operator ->()) ){
 
658
      int  D = O->Distance(Pos,Scales());
543
659
      if( D <= MinDist ){
544
660
        MinDist=D;
545
661
        ClosestItem=I;
558
674
};
559
675
 
560
676
 
561
 
void  sChartViewport::SetScale (rcsScale  scale)
562
 
{
563
 
  TheScale=scale;
564
 
  emit ScaleChanged();
565
 
};
566
 
 
567
 
 
568
 
void  sChartViewport::ChangeScale (rcsScale  scale)
569
 
{
570
 
  ScaleHistory.push(TheScale);
571
 
  SetScale(scale);
572
 
};
573
 
 
574
 
 
575
 
void  sChartViewport::SetReference (sPoint  P)
 
677
sChartScales  sChartViewport::ChartScales () const
 
678
{
 
679
  return sChartScales(sChartScale(XAxis->Variable,XAxis->PhysRange())
 
680
                    ,sChartScale(YAxis->Variable,YAxis->PhysRange()) );
 
681
};
 
682
 
 
683
 
 
684
void  sChartViewport::SetChartScales (sChartScales  scales)
 
685
{
 
686
  XAxis->Variable = scales.X.Name;
 
687
  XAxis->SetRange(scales.X.Range);
 
688
  YAxis->Variable = scales.Y.Name;
 
689
  YAxis->SetRange(scales.Y.Range);
 
690
  emit ScalesChanged();
 
691
};
 
692
 
 
693
 
 
694
void  sChartViewport::ChangeChartScales (sChartScales  scales)
 
695
{
 
696
  ScalesHistory.push(ChartScales());
 
697
  SetChartScales(scales);
 
698
};
 
699
 
 
700
 
 
701
void  sChartViewport::SetReference (sPhysPair  P)
576
702
{
577
703
  TheReference=P;
578
704
};
579
705
 
580
706
 
 
707
void  sChartViewport::SetReference (QPoint  P)
 
708
{
 
709
  TheReference=Tr(P);
 
710
};
 
711
 
 
712
 
581
713
void  sChartViewport::SetNominalSize (QSize S)
582
714
{
583
715
  NominalSize=S;
590
722
};
591
723
 
592
724
 
593
 
QPoint  sChartViewport::Value2Offset (rcsPoint  point)
594
 
{
595
 
  return QPoint( NominalOrigin.x()
596
 
                +Round( NominalSize.width()*( (point.X-TheScale.From.X)
597
 
                                      /(TheScale.To.X-TheScale.From.X)) )
598
 
               , NominalOrigin.y()
599
 
                +Round( NominalSize.height()*( (TheScale.To.Y-point.Y)
600
 
                                       /(TheScale.To.Y-TheScale.From.Y)) ) );
601
 
};
602
 
 
603
 
 
604
 
sPoint  sChartViewport::Offset2Value (const QPoint &  position)
605
 
{
606
 
  return sPoint( TheScale.From.X
607
 
               +(position.x()-NominalOrigin.x())*(TheScale.To.X-TheScale.From.X)
608
 
                                             /NominalSize.width()
609
 
               , TheScale.To.Y
610
 
               -(position.y()-NominalOrigin.y())*(TheScale.To.Y-TheScale.From.Y)
611
 
                                             /NominalSize.height()  );
 
725
QPoint  sChartViewport::Tr (sPhysPair  point) const
 
726
{
 
727
  return QPoint( XAxis->Tr(point.X) , YAxis->Tr(point.Y) );
 
728
};
 
729
 
 
730
 
 
731
QPoint  sChartViewport::Tr (rcsPoint  point) const
 
732
{
 
733
  return QPoint( XAxis->Tr(point.X) , YAxis->Tr(point.Y) );
 
734
};
 
735
 
 
736
 
 
737
sPhysPair  sChartViewport::Tr (QPoint  point) const
 
738
{
 
739
  return sPhysPair( XAxis->Tr(point.x()) , YAxis->Tr(point.y()) );
612
740
};
613
741
 
614
742
 
615
743
void  sChartViewport::ZoomOut ()
616
744
{
617
 
  real                        OldRangeX;
618
 
  real                        OldRangeY;
619
 
  sScale                      NewScale(TheScale);
620
 
  OldRangeX = TheScale.To.X - TheScale.From.X;
621
 
  OldRangeY = TheScale.To.Y - TheScale.From.Y;
622
 
  NewScale.From.X -= 0.5*(ZoomOutFactor-1.0)*OldRangeX;
623
 
  NewScale.To.X   += 0.5*(ZoomOutFactor-1.0)*OldRangeX;
624
 
  NewScale.From.Y -= 0.5*(ZoomOutFactor-1.0)*OldRangeY;
625
 
  NewScale.To.Y   += 0.5*(ZoomOutFactor-1.0)*OldRangeY;
626
 
  ScaleHistory.push(TheScale);
627
 
  SetScale(NewScale);
 
745
  ScalesHistory.push(ChartScales());
 
746
  XAxis->SetRange( - 0.5*(ZoomOutFactor-1.0)*NominalSize.width()
 
747
                 ,   0.5*(ZoomOutFactor+1.0)*NominalSize.width() );
 
748
  YAxis->SetRange(   0.5*(ZoomOutFactor+1.0)*NominalSize.height()
 
749
                 , - 0.5*(ZoomOutFactor-1.0)*NominalSize.height() );
 
750
  emit ScalesChanged();
628
751
};
629
752
 
630
753
 
631
754
void  sChartViewport::RescaleBack ()
632
755
{
633
 
  if( ! ScaleHistory.empty() ){
634
 
    SetScale(ScaleHistory.top());
635
 
    ScaleHistory.pop();
 
756
  if( ! ScalesHistory.empty() ){
 
757
    SetChartScales(ScalesHistory.top());
 
758
    ScalesHistory.pop();
636
759
  };
637
760
};
638
761
 
639
762
 
640
763
void  sChartViewport::RescaleToShowAll ()
641
764
{
642
 
  sBoundaries                 B;
643
 
  real                        S;
644
 
  ScaleHistory.push(TheScale);
645
 
  B=BoundariesForAllObjects();
646
 
  if( B.X.Undefined )
647
 
    B.X=sRange(0.0,10.0);
648
 
  if( B.Y.Undefined )
649
 
    B.Y=sRange(0.0,10.0);
650
 
  if( B.X.To < B.X.From )
651
 
    B.X.To=B.X.From;
652
 
  if( B.Y.To < B.Y.From )
653
 
    B.Y.To=B.Y.From;
654
 
  S=(B.X.To-B.X.From);
655
 
  if( S > 1e-30 ){
656
 
    TheScale.From.X = B.X.From - 0.05*S;
657
 
    TheScale.To.X   = B.X.To   + 0.05*S;
658
 
  };
659
 
  S=(B.Y.To-B.Y.From);
660
 
  if( S > 1e-30 ){
661
 
    TheScale.From.Y = B.Y.From - 0.05*S;
662
 
    TheScale.To.Y   = B.Y.To   + 0.05*S;
663
 
  };
664
 
  emit ScaleChanged();
 
765
  sBoundaries                 B( BoundariesForAllObjects() );
 
766
//  RANet::Log.Put(sLog::Debug,"Graph"
 
767
//      ,sString("Boundaries: X: ")+B.X.Text()+"  Y: "+B.Y.Text());
 
768
  ScalesHistory.push(ChartScales());
 
769
  XAxis->SetRange(sPhysRange( B.X.From() - 0.05*B.X.Size()
 
770
                            , B.X.To()   + 0.05*B.X.Size() ));
 
771
  YAxis->SetRange(sPhysRange( B.Y.From() - 0.05*B.Y.Size()
 
772
                            , B.Y.To()   + 0.05*B.Y.Size() ));
 
773
  emit ScalesChanged();
665
774
};
666
775
 
667
776
 
668
777
sBoundaries  sChartViewport::BoundariesForAllObjects ()
669
778
{
 
779
  RANet::Log.OpenBlock(sLog::Debug,"sChartViewport::BoundariesForAllObjects");
 
780
  int                         NumberOfVisibleGraphObjects = 0;
 
781
  sBoundaries                 B;
 
782
  sBoundaries                 B_of_the_first;
670
783
  sBoundaries                 TotalB;
671
 
  sBoundaries                 B;
 
784
 
 
785
  TotalB = sBoundaries( sPhysRange(real_nan,real_nan,_Unitsless_)
 
786
                      , sPhysRange(real_nan,real_nan,_Unitsless_) );
672
787
  sNet2TreeEvolution::psItem  I = Evolution->FirstVisible();
673
788
  while( I ){
674
 
//    s2DVisibleObject::sPtr    NodePtr(I->AttrValue());
675
 
    /*! @todo{patch} заплатка */
676
 
    sCurve::sPtr              NodePtr(I->AttrValue());
677
 
    if( NodePtr.IsCorrect() ){
678
 
      B= NodePtr->Boundaries();
679
 
      if( !B.X.Undefined ){
680
 
        if( TotalB.X.Undefined ){
681
 
          TotalB.X.From=B.X.From;
682
 
          TotalB.X.To=B.X.To;
683
 
          TotalB.X.Undefined=false;
684
 
        }else{
685
 
          if( TotalB.X.From > B.X.From )
686
 
            TotalB.X.From=B.X.From;
687
 
          if( TotalB.X.To < B.X.To )
688
 
            TotalB.X.To=B.X.To;
689
 
        };
690
 
      };
691
 
      if( !B.Y.Undefined ){
692
 
        if( TotalB.Y.Undefined ){
693
 
          TotalB.Y.From=B.Y.From;
694
 
          TotalB.Y.To=B.Y.To;
695
 
          TotalB.Y.Undefined=false;
696
 
        }else{
697
 
          if( TotalB.Y.From > B.Y.From )
698
 
            TotalB.Y.From=B.Y.From;
699
 
          if( TotalB.Y.To < B.Y.To )
700
 
            TotalB.Y.To=B.Y.To;
701
 
        };
702
 
      };
 
789
    if( psGraphObject  O = dynamic_cast<psGraphObject>
 
790
                                           (I->AttrValue().operator ->()) ){
 
791
      sBoundaries                 BB(sPhysRange(XAxis->Scale().Unit().Units())
 
792
                                    ,sPhysRange(YAxis->Scale().Unit().Units())
 
793
                                      );
 
794
      NumberOfVisibleGraphObjects++;
 
795
      B = O->Boundaries();
 
796
      RANet::Log.Put(sLog::Debug,"sChartViewport::BoundariesForAllObjects"
 
797
          ,sString("O->Boundaries: X: ")+B.X.Text()+"  Y:"+B.Y.Text());
 
798
      if( NumberOfVisibleGraphObjects == 1 ){
 
799
        B_of_the_first = B;
 
800
      };
 
801
      try{
 
802
        if(       ! B.X.From().IsNaN() && ! B.X.To().IsNaN()
 
803
               && ! B.Y.From().IsNaN() && ! B.Y.To().IsNaN() ){
 
804
          BB.X = B.X;
 
805
          BB.Y = B.Y;
 
806
          if( TotalB.X.From().IsNaN() ){
 
807
            TotalB.X = BB.X;
 
808
          }else{
 
809
            TotalB.X |= BB.X;
 
810
          };
 
811
          if( TotalB.Y.From().IsNaN() ){
 
812
            TotalB.Y = BB.Y;
 
813
          }else{
 
814
            TotalB.Y |= BB.Y;
 
815
          };
 
816
        }else if( ! B.X.From().IsNaN() && ! B.X.To().IsNaN() ){
 
817
          BB.X = B.X;
 
818
          if( TotalB.X.From().IsNaN() ){
 
819
            TotalB.X = BB.X;
 
820
          }else{
 
821
            TotalB.X |= BB.X;
 
822
          };
 
823
        }else if( ! B.Y.From().IsNaN() && ! B.Y.To().IsNaN() ){
 
824
          BB.Y = B.Y;
 
825
          if( TotalB.Y.From().IsNaN() ){
 
826
            TotalB.Y = BB.Y;
 
827
          }else{
 
828
            TotalB.Y |= BB.Y;
 
829
          };
 
830
        };
 
831
      }catch(rxRAlgebra){};
 
832
      RANet::Log.Put(sLog::Debug,"sChartViewport::BoundariesForAllObjects"
 
833
          ,sString("BB.X: ")+BB.X.Text()+"  BB.Y:"+BB.Y.Text());
 
834
      RANet::Log.Put(sLog::Debug,"sChartViewport::BoundariesForAllObjects"
 
835
          ,sString("TotalB.X: ")+TotalB.X.Text()+"  TotalB.Y:"+TotalB.Y.Text());
703
836
    };
704
837
    I=I->NextVisible();
705
838
  };
 
839
  if( NumberOfVisibleGraphObjects == 0 ){
 
840
    TotalB = sBoundaries(XAxis->PhysRange(),YAxis->PhysRange());
 
841
  }else if( NumberOfVisibleGraphObjects == 1 ){
 
842
    TotalB = B_of_the_first;
 
843
  }else{
 
844
    if(       TotalB.X.From().IsInf() ){
 
845
      TotalB.X = sPhysRange(XAxis->PhysRange().From(),TotalB.X.To());
 
846
    }else if( TotalB.X.To().IsInf() ){
 
847
      TotalB.X = sPhysRange(TotalB.X.From()          ,XAxis->PhysRange().To());
 
848
    }else if( TotalB.Y.From().IsInf() ){
 
849
      TotalB.Y = sPhysRange(YAxis->PhysRange().From(),TotalB.Y.To());
 
850
    }else if( TotalB.Y.To().IsInf() ){
 
851
      TotalB.Y = sPhysRange(TotalB.Y.From()          ,YAxis->PhysRange().To());
 
852
    };
 
853
  };
 
854
  RANet::Log.Put(sLog::Debug,"sChartViewport::BoundariesForAllObjects"
 
855
      ,sString("TotalB: X: ")+TotalB.X.Text()+"  Y: "+TotalB.Y.Text());
 
856
  RANet::Log.CloseBlock(sLog::Debug,"sChartViewport::BoundariesForAllObjects");
706
857
  return TotalB;
707
858
};
708
859
 
717
868
//  };
718
869
  sNet2TreeEvolution::psItem  I = Evolution->FirstVisible();
719
870
  while( I ){
720
 
//    s2DVisibleObject::sPtr    NodePtr(I->AttrValue());
721
 
//    if( NodePtr.IsCorrect() ){
722
 
//      sCurve::sPtr              CurvePtr(NodePtr);
723
 
      sCurve::sPtr              CurvePtr(I->AttrValue());
724
 
      if( CurvePtr.IsCorrect() ){
725
 
        (*DrawProc)(&painter,this,I);
726
 
      };
727
 
      if( true /*sMark*/ ){
728
 
//        поиск принадлежности среди предков по эволюции
729
 
      };
 
871
//    if( /*psCurve  O =*/ dynamic_cast<psCurve>
 
872
//                                           (I->AttrValue().operator ->()) ){
 
873
//      (*DrawProc)(&painter,this,I);
 
874
//    }else if( true /*sMark*/ ){
 
875
//      //поиск принадлежности среди предков по эволюции
730
876
//    };
 
877
    psGraphObject           Object(dynamic_cast<psGraphObject>
 
878
                                                (I->AttrValue().operator ->()));
 
879
    if( Object ){
 
880
      psAppearance                ObjectAppearance(Object->Appearance);
 
881
      for( list<pcfDrawProc>::const_iterator  i = DrawProcCollection.begin()
 
882
                                            ; i != DrawProcCollection.end()
 
883
                                            ; ++i){
 
884
        if( (*i)(&painter,this,Object,ObjectAppearance) )  break;
 
885
      };
 
886
    };
731
887
    I=I->NextVisible();
732
888
  };
733
 
  QPen                        Pen=painter.pen();
734
 
  Pen.setStyle(Qt::DotLine);
735
 
  painter.setPen(Pen);
736
 
  painter.drawLine(Value2Offset(sPoint(TheScale.From.X,TheReference.Y))
737
 
                   ,Value2Offset(sPoint(TheScale.To.X  ,TheReference.Y)));
738
 
  painter.drawLine(Value2Offset(sPoint(TheReference.X,TheScale.From.Y))
739
 
                   ,Value2Offset(sPoint(TheReference.X,TheScale.To.Y)));
740
 
}
 
889
  try{
 
890
    QPoint                      R(Tr(TheReference));
 
891
    QPen                        Pen=painter.pen();
 
892
    Pen.setStyle(Qt::DotLine);
 
893
    painter.setPen(Pen);
 
894
    painter.drawLine(0     ,R.y() ,size().width() ,R.y());
 
895
    painter.drawLine(R.x() ,0     ,R.x()          ,size().height());
 
896
  }catch(rxRAlgebra){};
 
897
};
741
898
 
742
899
 
743
900
void  sChartViewport::keyPressEvent (QKeyEvent *  event)
747
904
  }else{
748
905
 
749
906
  };
750
 
}
 
907
};
751
908
 
752
909
 
753
910
void sChartViewport::mousePressEvent (QMouseEvent *  event)
765
922
      MouseOperationStarted=true;
766
923
      MouseOperationType=MovingFrame;
767
924
      MouseOperationLastPosition = event->pos();
768
 
      ScaleHistory.push(TheScale);
 
925
      ScalesHistory.push(ChartScales());
769
926
      setCursor(*ShiftingCursor);
770
927
//    }else if( Host->StartDraggingAnObjectIfAny() ){
771
928
//      Host->MouseOperationStarted=true;
781
938
  }else{
782
939
    MouseOperationStarted=false;
783
940
  };
784
 
}
 
941
};
785
942
 
786
943
 
787
944
void sChartViewport::mouseReleaseEvent (QMouseEvent *  event)
791
948
      if( MouseOperationType == MovingInitialPoint ){
792
949
        MouseOperationStarted=false;
793
950
        SetReference(event->pos());
794
 
        emit CursorPositionChanged(Offset2Value(event->pos())
795
 
                                  ,TheReference);
 
951
        emit CursorPositionChanged(event->pos());
796
952
        update();
797
953
      }else if( MouseOperationType == MovingFrame ){
798
954
        if( (event->pos() == MouseOperationStartPosition)
799
 
            && ! ScaleHistory.empty() ){
800
 
          ScaleHistory.pop();
 
955
            && ! ScalesHistory.empty() ){
 
956
          ScalesHistory.pop();
801
957
        };
802
958
      }else if( MouseOperationType == Zooming ){
803
959
        ZoomRect->hide();
804
960
        if( (ZoomRect->width() > 2) && (ZoomRect->height() > 2) ){
805
 
          sScale                  S;
806
 
          S.From=Offset2Value(QPoint(ZoomRect->pos().x()
807
 
                                    ,ZoomRect->pos().y() + ZoomRect->height()));
808
 
          S.To=  Offset2Value(QPoint(ZoomRect->pos().x() + ZoomRect->width()
809
 
                                    ,ZoomRect->pos().y()                     ));
810
 
          ScaleHistory.push(TheScale);
811
 
          SetScale(S);
 
961
          ScalesHistory.push(ChartScales());
 
962
          XAxis->SetRange( ZoomRect->pos().x()
 
963
                         , ZoomRect->pos().x() + ZoomRect->width()  );
 
964
          YAxis->SetRange( ZoomRect->pos().y() + ZoomRect->height()
 
965
                         , ZoomRect->pos().y()                      );
 
966
          emit ScalesChanged();
812
967
        };
813
968
      };
814
969
//      if( Shift.Contains(ssCtrl) ){
836
991
 
837
992
void sChartViewport::mouseMoveEvent (QMouseEvent *  event)
838
993
{
839
 
  emit CursorPositionChanged(Offset2Value(event->pos()),TheReference);
 
994
  emit CursorPositionChanged(event->pos());
840
995
  if( event->buttons() & Qt::LeftButton ) {
841
996
    if( MouseOperationStarted ){
842
997
      if( MouseOperationType == MovingInitialPoint ){
844
999
        update();
845
1000
      }else if( MouseOperationType == MovingFrame ){
846
1001
        if( (event->pos() - MouseOperationLastPosition).manhattanLength() > 3 ){
847
 
          sPoint  Shift = Offset2Value(MouseOperationLastPosition)
848
 
                         -Offset2Value(event->pos());
849
 
          SetScale(sScale(TheScale.From+Shift,TheScale.To+Shift));
 
1002
          XAxis->ShiftRange( MouseOperationLastPosition.x() - event->pos().x() );
 
1003
          YAxis->ShiftRange( MouseOperationLastPosition.y() - event->pos().y() );
 
1004
          emit ScalesChanged();
850
1005
          MouseOperationLastPosition=event->pos();
851
1006
        };
852
1007
      }else if( MouseOperationType == Zooming ){
874
1029
//    MouseOperationStarted=false;
875
1030
//    DragIsAboutToStart = false;
876
1031
//  };
877
 
}
 
1032
};
878
1033
 
879
1034
 
880
1035
void sChartViewport::mouseDoubleClickEvent (QMouseEvent *  event)
893
1048
void  sChartViewport::dragEnterEvent (QDragEnterEvent *  event)
894
1049
{
895
1050
  if( event->mimeData()
896
 
           ->hasFormat(sString2QString(sNet2TreeEvolution::sItem::MimeType)) ){
897
 
    sCurve::sPtr              Curve(sNet2TreeEvolution::sItem::DraggedItem
 
1051
           ->hasFormat(ToQString(sNet2TreeEvolution::sItem::MimeType)) ){
 
1052
    sDependence::sPtr           Curve(sNet2TreeEvolution::sItem::DraggedItem
898
1053
                                                                ->AttrValue());
899
1054
    if( Curve.IsCorrect() ){
900
1055
      event->setDropAction(Qt::LinkAction);
907
1062
void  sChartViewport::dropEvent (QDropEvent *  event)
908
1063
{
909
1064
  if( event->mimeData()
910
 
           ->hasFormat(sString2QString(sNet2TreeEvolution::sItem::MimeType)) ){
911
 
    sCurve::sPtr              Curve(sNet2TreeEvolution::sItem::DraggedItem
 
1065
           ->hasFormat(ToQString(sNet2TreeEvolution::sItem::MimeType)) ){
 
1066
    sDependence::sPtr           Curve(sNet2TreeEvolution::sItem::DraggedItem
912
1067
                                                                ->AttrValue());
913
1068
    if( Curve.IsCorrect() ){
914
1069
      event->setDropAction(Qt::LinkAction);
917
1072
                                                 ,Curve
918
1073
                                                 ,sNode::Type()));
919
1074
      Evolution->Update();
920
 
      RescaleToShowAll();
 
1075
      sBoundaries                 B( Curve->Boundaries() );
 
1076
      ScalesHistory.push(ChartScales());
 
1077
      XAxis->SetRange(sPhysRange( B.X.From() - 0.05*B.X.Size()
 
1078
                                , B.X.To()   + 0.05*B.X.Size() ));
 
1079
      YAxis->SetRange(sPhysRange( B.Y.From() - 0.05*B.Y.Size()
 
1080
                                , B.Y.To()   + 0.05*B.Y.Size() ));
 
1081
      try{
 
1082
        ScalesHistory.top().X.Range.Units().ToBasic() + B.X.Units().ToBasic();
 
1083
      }catch(rxRAlgebra){
 
1084
        XAxis->Variable = "";
 
1085
      };
 
1086
      try{
 
1087
        ScalesHistory.top().Y.Range.Units().ToBasic() + B.Y.Units().ToBasic();
 
1088
      }catch(rxRAlgebra){
 
1089
        YAxis->Variable = "";
 
1090
      };
 
1091
      emit ScalesChanged();
 
1092
//      RescaleToShowAll();
921
1093
    };
922
1094
  };
923
1095
};
954
1126
    (*(MyAction->DoIt))(TreeItem,sPoint(event->pos().x(),event->pos().y()));
955
1127
    Evolution->Update();
956
1128
  };
957
 
}
 
1129
};
 
1130
 
 
1131
 
 
1132
void  sChartViewport::OnCursorPositionChanged (QPoint  cursor)
 
1133
{
 
1134
  sPhysPair                   Cursor(XAxis->Tr(cursor.x())
 
1135
                                    ,YAxis->Tr(cursor.y()));
 
1136
  emit CursorPositionChanged(Cursor ,Reference()
 
1137
                            ,XAxis->Variable ,YAxis->Variable);
 
1138
};
958
1139
 
959
1140
//-------------------------------------------------------------- sChart ---
960
1141
 
961
1142
sChart::~sChart ()
962
1143
{
963
1144
  if( Viewport ){ delete Viewport;  Viewport=NULL; };
 
1145
  if( XAxis ){ delete XAxis;  XAxis=NULL; };
 
1146
  if( YAxis ){ delete YAxis;  YAxis=NULL; };
964
1147
};
965
1148
 
966
1149
sChart::sChart (psNet2TreeEvolution  evolution
967
1150
               ,QWidget *            parent)
968
1151
  :QFrame(parent)
969
 
  ,Viewport( new sChartViewport(evolution,this) )
 
1152
  ,XAxis( new sX_Axis )
 
1153
  ,YAxis( new sY_Axis )
 
1154
  ,Viewport( new sChartViewport(XAxis,YAxis,evolution,this) )
970
1155
//  ,Margins(10,30,60,10)
971
1156
  ,Margins(10,40,70,10)
972
1157
{
973
1158
//  setContextMenuPolicy(Qt::DefaultContextMenu);
974
1159
  setStyleSheet("QFrame {background: white; border: 1px solid grey}");
975
1160
  UpdateAxes();
976
 
  connect(Viewport,SIGNAL(ScaleChanged()),this,SLOT(UpdateAxes()));
977
 
  connect(Viewport,SIGNAL(CursorPositionChanged(sPoint,sPoint))
978
 
         ,this    ,SLOT(OnCursorMove(sPoint,sPoint)));
 
1161
  connect(Viewport,SIGNAL(ScalesChanged()),this,SLOT(UpdateAxes()));
 
1162
  connect(Viewport ,SIGNAL(CursorPositionChanged(sPhysPair,sPhysPair
 
1163
                                                ,sString,sString))
 
1164
         ,this     ,SIGNAL(CursorPositionChanged(sPhysPair,sPhysPair
 
1165
                                                ,sString,sString)));
979
1166
 
980
1167
  QAction *                   A;
981
1168
  A = new QAction(QIcon(":/RAGUI/icons/zoomout.png") ,tr("Zoom out") ,this);
987
1174
  addAction(A);
988
1175
  A = new QAction(QIcon(":/RAGUI/icons/rescaleback.png")
989
1176
                 ,tr("Return to previous scale") ,this);
990
 
  /*! @todo{shortcuts} it sets up a global shortcut (ignores key focus);
 
1177
  /*! @todo{UI++} it sets up a global shortcut (ignores key focus);
991
1178
  if there are 2 Charts, it says: ambigous shortcut*/
992
1179
//  A->setShortcut(Qt::Key_Backspace);
993
1180
  connect(A,SIGNAL(triggered()),this,SLOT(RescaleBack()));
1001
1188
};
1002
1189
 
1003
1190
 
 
1191
void  sChart::RestoreScales (sCluster::sPtr  C)
 
1192
{
 
1193
  if( C.IsCorrect() ){
 
1194
    sTextNode::sPtr           V;
 
1195
    sPhysRangeNode::sPtr      R;
 
1196
    V=C->GetAttr("ScaleX.Variable");
 
1197
    if( V.IsCorrect() )  XAxis->Variable=V->Value();
 
1198
    V=C->GetAttr("ScaleY.Variable");
 
1199
    if( V.IsCorrect() )  YAxis->Variable=V->Value();
 
1200
 
 
1201
    R=C->GetAttr("ScaleX.Range");
 
1202
    if( R.IsCorrect() )  XAxis->SetRange((sPhysRange)(*R));
 
1203
    R=C->GetAttr("ScaleY.Range");
 
1204
    if( R.IsCorrect() )  YAxis->SetRange((sPhysRange)(*R));
 
1205
    UpdateAxes();
 
1206
  };
 
1207
};
 
1208
 
 
1209
 
 
1210
void  sChart::StoreScales (sCluster::sPtr  C) const
 
1211
{
 
1212
  if( C.IsCorrect() ){
 
1213
    C   << attr("ScaleX.Variable",XAxis->Variable)
 
1214
        << attr("ScaleX.Range",XAxis->PhysRange())
 
1215
        << attr("ScaleY.Variable",YAxis->Variable)
 
1216
        << attr("ScaleY.Range",YAxis->PhysRange());
 
1217
  };
 
1218
};
 
1219
 
 
1220
 
 
1221
void  sChart::SetChartScales (sChartScales  scales)
 
1222
{
 
1223
  Viewport->SetChartScales(scales);
 
1224
};
 
1225
 
 
1226
 
1004
1227
void  sChart::AllowCurveDrops (bool  Allow)
1005
1228
{
1006
1229
  Viewport->AllowCurveDrops(Allow);
1010
1233
void  sChart::paintEvent (QPaintEvent *)
1011
1234
{
1012
1235
  QPainter                    painter(this);
1013
 
  X_Axis.Draw(&painter);
1014
 
  Y_Axis.Draw(&painter);
 
1236
  XAxis->Draw(&painter);
 
1237
  YAxis->Draw(&painter);
1015
1238
};
1016
1239
 
1017
1240
 
1039
1262
 
1040
1263
void  sChart::EditScales ()
1041
1264
{
1042
 
  sSetScalesDlg               D(parentWidget());
1043
 
  D.field_OrdinateMetricPrefix->setCurrentIndex(Y_Axis.MultiplierExponent/3 + 8);
1044
 
  D.field_OrdinateFrom->setValue(Viewport->Scale().Y().From / Y_Axis.Multiplier);
1045
 
  D.field_OrdinateTo->setValue(Viewport->Scale().Y().To / Y_Axis.Multiplier);
1046
 
  D.field_AbscissMetricPrefix->setCurrentIndex(X_Axis.MultiplierExponent/3 + 8);
1047
 
  D.field_AbscissFrom->setValue(Viewport->Scale().X().From / X_Axis.Multiplier);
1048
 
  D.field_AbscissTo->setValue(Viewport->Scale().X().To / X_Axis.Multiplier);
 
1265
  sScalesDlg                  D(parentWidget());
 
1266
  D.fldAbscissVariableName->setText(ToQString(XAxis->Variable));
 
1267
  D.fldOrdinateVariableName->setText(ToQString(YAxis->Variable));
 
1268
  D.fldAbscissRange->SetValue(XAxis->PhysRange());
 
1269
  D.fldOrdinateRange->SetValue(YAxis->PhysRange());
1049
1270
  if( D.exec() ){
1050
 
    int  OrdinateExp = (D.field_OrdinateMetricPrefix->currentIndex()-8)*3;
1051
 
    int  AbscissExp = (D.field_AbscissMetricPrefix->currentIndex()-8)*3;
1052
 
    Viewport->ChangeScale(sScale(sPoint(D.field_AbscissFrom->value()
1053
 
                                                    *power10(AbscissExp)
1054
 
                                       ,D.field_OrdinateFrom->value()
1055
 
                                                    *power10(OrdinateExp))
1056
 
                                ,sPoint(D.field_AbscissTo->value()
1057
 
                                                    *power10(AbscissExp)
1058
 
                                       ,D.field_OrdinateTo->value()
1059
 
                                                    *power10(OrdinateExp)) ));
 
1271
    Viewport->ChangeChartScales(sChartScales
 
1272
        (sChartScale(FromQString(D.fldAbscissVariableName->text().simplified())
 
1273
                   ,D.fldAbscissRange->Value())
 
1274
        ,sChartScale(FromQString(D.fldOrdinateVariableName->text().simplified())
 
1275
                   ,D.fldOrdinateRange->Value())
 
1276
        ));
1060
1277
    UpdateAxes();
1061
1278
  };
1062
1279
};
1074
1291
                                                  );
1075
1292
  int                         AxisLinewidth = 1;
1076
1293
 
1077
 
  X_Axis.Range=Viewport->Scale().X();
1078
 
  Y_Axis.Range=Viewport->Scale().Y();
1079
1294
  Viewport->SetNominalSize(ViewportNominalSize);
1080
 
  X_Axis.NominalSize=ViewportNominalSize.width();
1081
 
  Y_Axis.NominalSize=ViewportNominalSize.height();
 
1295
  XAxis->SetSize(ViewportNominalSize.width());
 
1296
  YAxis->SetSize(ViewportNominalSize.height());
1082
1297
 
1083
 
  X_Axis.PenWidth=AxisLinewidth;
1084
 
  Y_Axis.PenWidth=AxisLinewidth;
1085
 
  X_Axis.Origin=QPoint( TopLeft.x()
 
1298
  XAxis->SetPenWidth(AxisLinewidth);
 
1299
  YAxis->SetPenWidth(AxisLinewidth);
 
1300
  XAxis->Origin=QPoint( TopLeft.x()
1086
1301
                      , TopLeft.y() + ViewportNominalSize.height() );
1087
 
  X_Axis.OppositeOrigin=QPoint( TopLeft.x() , TopLeft.y() );
1088
 
  Y_Axis.Origin=QPoint( X_Axis.Origin.x() , X_Axis.Origin.y() );
1089
 
  Y_Axis.OppositeOrigin=QPoint(TopLeft.x() + ViewportNominalSize.width()
 
1302
  XAxis->OppositeOrigin=QPoint( TopLeft.x() , TopLeft.y() );
 
1303
  YAxis->Origin=QPoint( XAxis->Origin.x() , XAxis->Origin.y() );
 
1304
  YAxis->OppositeOrigin=QPoint(TopLeft.x() + ViewportNominalSize.width()
1090
1305
                              ,TopLeft.y() + ViewportNominalSize.height() );
1091
1306
 
1092
1307
  Viewport->resize(ViewportNominalSize.width()  - AxisLinewidth
1096
1311
  Viewport->move(Margins.Left() + (AxisLinewidth+1)/2
1097
1312
                ,Margins.Top()  + (AxisLinewidth+1)/2 );
1098
1313
 
1099
 
  X_Axis.Arrange(fontMetrics());
1100
 
  Y_Axis.Arrange(fontMetrics());
 
1314
  XAxis->Arrange(fontMetrics());
 
1315
  YAxis->Arrange(fontMetrics());
1101
1316
  setMinimumSize(40 + Margins.Left() + Margins.Right()
1102
1317
                ,40 + Margins.Top()  + Margins.Bottom() );
1103
1318
  update();
1104
1319
};
1105
1320
 
1106
 
 
1107
 
void  sChart::OnCursorMove (sPoint  cursor
1108
 
                           ,sPoint  reference_point)
1109
 
{
1110
 
  emit CursorPositionChanged(cursor,reference_point);
1111
 
  int                         digits = 0;
1112
 
  QString  X;
1113
 
  QString  DX;
1114
 
  QString  Y;
1115
 
  QString  DY;
1116
 
  QString  VarX("x");
1117
 
  QString  VarY("y");
1118
 
  sString  ExpText;
1119
 
  if( X_Axis.MultiplierExponent != 0 )
1120
 
    ((ExpText = "×10<sup>") << X_Axis.MultiplierExponent ) += "</sup> ";
1121
 
  if( X_Axis.PixelValue() / X_Axis.Multiplier < 0.999 ){
1122
 
    digits=-Round(log10(X_Axis.PixelValue() / X_Axis.Multiplier)-0.499);
1123
 
  };
1124
 
  X.setNum(double(cursor.X / X_Axis.Multiplier),'f',digits);
1125
 
  DX.setNum(double((cursor.X - reference_point.X) / X_Axis.Multiplier),'f',digits);
1126
 
  X = VarX + "= " + X + sString2QString(ExpText);
1127
 
  DX = QString::fromUtf8("Δ<sub>") + VarX + QString::fromUtf8("</sub>= ") + DX
1128
 
      + sString2QString(ExpText);
1129
 
 
1130
 
  ExpText = "";
1131
 
  if( Y_Axis.MultiplierExponent != 0 )
1132
 
    ((ExpText = "×10<sup>") << Y_Axis.MultiplierExponent ) += "</sup> ";
1133
 
  digits = 0;
1134
 
  if( Y_Axis.PixelValue() / Y_Axis.Multiplier < 0.999 ){
1135
 
    digits=-Round(log10(Y_Axis.PixelValue() / Y_Axis.Multiplier)-0.499);
1136
 
  };
1137
 
  Y.setNum(double(cursor.Y / Y_Axis.Multiplier),'f',digits);
1138
 
  DY.setNum(double((cursor.Y - reference_point.Y) / Y_Axis.Multiplier),'f',digits);
1139
 
  Y = VarY + "= " + Y + sString2QString(ExpText);
1140
 
  DY = QString::fromUtf8("Δ<sub>") + VarY + QString::fromUtf8("</sub>= ") + DY
1141
 
      + sString2QString(ExpText);
1142
 
  emit CursorInfo(X,DX,Y,DY);
1143
 
};
1144
 
 
1145
1321
//------------------------------------------------------------------------------
1146
1322
}; //namespace RA
1147
1323