OOFILE  1.9
oofDStyl.cpp
Go to the documentation of this file.
1 // COPYRIGHT 1996 A.D. Software, All rights reserved
2 
3 //=================================================================================
4 // oofDStyl.cp
5 //=================================================================================
6 
7 #include "oofpch_g.h" // for precompilation of graph files
8 
9 #ifndef H_OOFRECT
10  #include "oofRect.h"
11 #endif
12 #ifndef H_OOFDSTYL
13  #include "oofDStyl.h"
14 #endif
15 #ifndef H_OOFGRPHS
16  #include "oofGrphs.h"
17 #endif
18 #ifdef _Windows
19  #ifndef H_OOFDRAW
20  #include "oofdraw.h"
21  #endif
22 #endif
23 #include <string.h>
24 
25 #ifdef OOF_MEM_DEBUG_LAST_INCLUDE
26  #include OOF_MEM_DEBUG_LAST_INCLUDE
27 #endif
28 
29 #ifndef OOF_NO_STDLIB
30  #ifndef std
31  using namespace std;
32  #endif
33 #endif
34 
35 const unsigned int symbolWidth = 5;
36 const unsigned int symbolHeight = 5;
37 const unsigned int symbolOffsetX = symbolWidth/2;
38 const unsigned int symbolOffsetY = symbolHeight/2;
39 
40 //---------------------------------------------------------------------------------
41 // * oofDrawStyle
42 //---------------------------------------------------------------------------------
43 
44 
45 // static data members:
46 bool oofDrawStyle::sIsMono = false;
47 
49  const oofPattern& monoPat, const oofColor& bg,
50  oofSymbol *sym, bool adoptsSymbol)
51  //oofDrawStyle::symbolType sym)
52  : mForeColor(fg), mBackColor(bg)
53 #ifdef _Windows
54  ,mPen(oofPen::createPen(mForeColor))
55 #endif
56 {
57  // These patterns need to be owned in case the pattern reference which
58  // is passed in is destroyed.
59  mColorPattern = new oofPattern(colPat);
60  mMonoPattern = new oofPattern(monoPat);
61  if (sym) {
62  if (adoptsSymbol)
63  mSymbol = sym; // we now own this pointer, the caller loses it!
64  else
65  mSymbol = sym->clone();
66  }
67  else
68  mSymbol = 0; // zero pointer
69 }
70 
71 
73  mForeColor(rhs.mForeColor),
74  mBackColor(rhs.mBackColor)
75 #ifdef _Windows
76  ,mPen(rhs.mPen)
77 #endif
78 {
79  mColorPattern = new oofPattern(rhs.mColorPattern);
80  mMonoPattern = new oofPattern(rhs.mMonoPattern);
81  mSymbol = rhs.mSymbol->clone();
82 }
83 
85  mForeColor(rhs->mForeColor),
86  mBackColor(rhs->mBackColor)
87 #ifdef _Windows
88  ,mPen(rhs->mPen)
89 #endif
90 {
91  mColorPattern = new oofPattern(rhs->mColorPattern);
92  mMonoPattern = new oofPattern(rhs->mMonoPattern);
93  mSymbol = rhs->mSymbol->clone();
94 }
95 
96 
98 {
99  // Although both pattern pointers are created pointing at different
100  // storage, the user is allowed to set them to point at the same storage.
101  // Hence we must make a check to avoid a double delete.
102  if (mColorPattern!=mMonoPattern) {
103  delete mColorPattern;
104  delete mMonoPattern;
105  }
106  else
107  delete mColorPattern;
108  delete mSymbol;
109 }
110 
111 
112 const oofDrawStyle&
114 {
115  mForeColor = rhs.mForeColor;
116  mBackColor = rhs.mBackColor;
117 #ifdef _Windows
118  mPen = rhs.mPen;
119 #endif
120  if (mColorPattern!=mMonoPattern) {
121  delete mColorPattern;
122  delete mMonoPattern;
123  }
124  else
125  delete mColorPattern; // see destructor for rational for this logic
126  mColorPattern = new oofPattern(rhs.mColorPattern);
127  mMonoPattern = new oofPattern(rhs.mMonoPattern);
128  mSymbol = rhs.mSymbol;
129  return *this;
130 }
131 
132 
133 void
135 {
136  // This function sets *both the colour pattern *and the mono pattern to the
137  // pattern passed in.
138  // Since the two patterns may already point at the same piece of storage, a
139  // check is performed to avoid a double delete.
140  if (mColorPattern!=mMonoPattern) {
141  delete mColorPattern;
142  delete mMonoPattern;
143  mColorPattern = new oofPattern(inPattern);
144  mMonoPattern = mColorPattern;
145  }
146  else {
147  delete mColorPattern;
148  mColorPattern = new oofPattern(inPattern);
149  mMonoPattern = mColorPattern;
150  }
151 }
152 
153 
154 
155 
156 void
158 {
159  if (mColorPattern!=mMonoPattern) {
160  delete mColorPattern;
161  mColorPattern = new oofPattern(inPattern);
162  }
163  else
164  // We don't delete the storage because mMonoPattern is still using it.
165  mColorPattern = new oofPattern(inPattern);
166 }
167 
168 
169 void
171 {
172  if (mColorPattern!=mMonoPattern) {
173  delete mMonoPattern;
174  mMonoPattern = new oofPattern(inPattern);
175  }
176  else
177  // We don't delete the storage because mColorPattern is still using it.
178  mMonoPattern = new oofPattern(inPattern);
179 }
180 
181 
182 const oofColor&
184 {
185  return mForeColor;
186 }
187 
188 
189 const oofColor&
191 {
192  return mBackColor;
193 }
194 
195 
196 const oofPattern&
198 {
199  return *mColorPattern;
200 }
201 
202 
203 const oofPattern&
205 {
206  return *mMonoPattern;
207 }
208 
209 
210 const oofPattern&
212 {
213  if (isMono())
214  return *mMonoPattern;
215  else
216  return *mColorPattern;
217 }
218 
219 
220 void
222 {
223 #ifdef _Macintosh
224  if (isMono()) {
225  RGBColor black = {0,0,0},
226  white = {0xFFFF,0xFFFF,0xFFFF};
227  ::RGBForeColor(&black);
228  ::RGBBackColor(&white);
229  }
230  else {
231  ::RGBForeColor(foreColor());
232  ::RGBBackColor(backColor());
233  }
234 #elif defined _Windows
235  HDC hdc = oofCurrentDraw::getCurrentDC();
236  if (hdc) {
237  if (isMono()) {
238  ::SetTextColor(hdc, RGB(0, 0, 0));
239  ::SetBkColor(hdc, RGB(255, 255, 255));
240 
241  ::SelectObject(hdc, ::GetStockObject(BLACK_PEN)); // Include the Pen for outlining
242  }
243  else {
244  ::SetTextColor(hdc, foreColor());
245  ::SetBkColor(hdc, backColor());
246 
247  if (mPen)
248  ::SelectObject(hdc, mPen); // Include the Pen for outlining
249  }
250  }
251 #endif // OS
252 }
253 
254 
255 void
257 {
258  sIsMono = true;
259 }
260 
261 
262 void
264 {
265  sIsMono = false;
266 }
267 
268 
269 bool
271 {
272  return sIsMono;
273 }
274 
275 //---------------------------------------------------------------------------------
276 // oofDrawStyleArray
277 //---------------------------------------------------------------------------------
278 
279 
281 {
282 }
283 
284 
286 {
287  unsigned long numDrawStyles = mDrawStyles.count();
288  // delete all our owned pointers to draw styles
289  for (unsigned long index=0; index<numDrawStyles; index++)
290  delete (oofDrawStyle*) mDrawStyles.value(index);
291 }
292 
293 
294 void
296 {
297  // we OWN our styles
298  oofDrawStyle *ourDS = new oofDrawStyle(ds);
299  mDrawStyles.append((unsigned long)ourDS);
300 }
301 
302 
305 {
306  append(*ds);
307  return *this;
308 }
309 
310 
313 {
314  append(ds);
315  return *this;
316 }
317 
318 
319 const oofDrawStyle&
320 oofDrawStyleArray::item(unsigned long index) const
321 {
322 // the ELArray convention is that 'value' is const, 'item' is a ref
323  const oofDrawStyle* theStyle = (const oofDrawStyle*) mDrawStyles.value(index);
324  assert(theStyle);
325  return *theStyle;
326 }
327 
328 
334 void
336 {
337  OOF_ExpandableLongArray& rhsArray = inArray->mDrawStyles; // ugly intrusion into rhs
338  unsigned long numItems = rhsArray.count();
339  for (unsigned long index = 0; index<numItems; index++) {
340  mDrawStyles.append(rhsArray.value(index));
341  }
342  rhsArray.deleteAllCells(); // so other side won't think it still owns the pointers
343  // resets count, so its loop to set all to a value does nought!
344 }
345 
346 
347 unsigned long
349 {
350  return mDrawStyles.count();
351 }
352 
353 
354 //---------------------------------------------------------------------------------
355 // oofDrawStyleSet
356 //---------------------------------------------------------------------------------
357 
358 
361 oofDrawStyle(); };
362 
363 
366 {
367 // work out an algorithm for producing nice DrawStyles, based on the count so far
368  oofPattern monoPat(oofPattern::white);
369  oofSymbol* theSymbol;
370 
371  short genIndex = mNumDrawStylesProduced % 8;
372  switch (genIndex) {
373  case 0:
374  monoPat.set(oofPattern::ltdots);
375  theSymbol = new oofSquareSymbol;
376  break;
377 
378  case 1:
379  monoPat.set(oofPattern::ltstripes);
380  theSymbol = new oofCircleSymbol;
381  break;
382 
383  case 2:
384  monoPat.set(oofPattern::dots);
385  theSymbol = new oofCrossSymbol;
386  break;
387 
388  case 3:
389  monoPat.set(oofPattern::stripes);
390  theSymbol = new oofEcsSymbol;
391  break;
392 
393  case 4:
394  monoPat.set(oofPattern::ltgray);
395  theSymbol = new oofSquareSymbol;
396  break;
397 
398  case 5:
399  monoPat.set(oofPattern::dkdots);
400  theSymbol = new oofCircleSymbol;
401  break;
402 
403  case 6:
404  monoPat.set(oofPattern::gray);
405  theSymbol = new oofCrossSymbol;
406  break;
407 
408  case 7:
409  monoPat.set(oofPattern::dkstripes);
410  theSymbol = new oofSquareSymbol;
411  break;
412 
413  case 8:
414  monoPat.set(oofPattern::dkgray);
415  theSymbol = new oofCircleSymbol;
416  break;
417 
418  case 9:
419  monoPat.set(oofPattern::black);
420  theSymbol = new oofCrossSymbol;
421  break;
422 
423  default:
424  monoPat.set(oofPattern::white);
425  theSymbol = new oofEcsSymbol;
426  break;
427 
428  };
429 
430 /*
431  if (mColorSet) // or something like this
432  // use the colour set's nth item
433 */
434 
435 
436 
438  oofColor back = oofColor::White; // by default
439  oofPattern colPat = fore; // oofPattern::gray; // by default
440 
441  ++mNumDrawStylesProduced; // will start from 0
442 
443  return oofDrawStyle(fore,colPat,monoPat,back,theSymbol, true /* adoptsSymbol */);
444 };
445 
446 
447 oofColor
449 {
450  typedef const unsigned short indexT;
451  typedef unsigned short colorT;
452 
453  indexT kNumPrimQuanta = 5; // size of following list
454  indexT kNumSecQuanta = 10; // size of following list
455 
456  // we want to start at 0 to force pure R G B to be first out
457  // to avoid repeats, we do
458  // 0 ... 20000 against radial 0 = 4 combos
459  // 65535 ... 20000 against radial 20700 = 3 combos
460  // 65535 ... 20000 against radial 37000 = 3 combos
461  // 65535 ... 43000 against radial 49000 = 2 combos - NO TOO LIGHT
462  const colorT secQuanta[] = {
463  0, 65535, 43000, 20000,
464  65535, 43000, 20000,
465  65535, 43000, 20000
466  };
467 
468  const colorT radialQuanta[] = {
469  0, 0, 0, 0,
470  20700, 20700, 20700,
471  37000, 37000, 37000
472  };
473 
474 
475  const colorT primQuanta[] = {65535, 49000, 37000, 20700, 0};
476  indexT kNumPrim = 3; // 3 primary colours
477 
478 
479 // for each primary number
480 // we do a factorial of mixes
481 // then we lower the primary number to get darker colours
482  indexT mixIndex = index % kNumPrim;
483  indexT kNumMix = index / kNumPrim;
484  indexT secIndex = kNumMix % kNumSecQuanta;
485  indexT primIndex = (kNumMix / kNumSecQuanta) % kNumPrimQuanta;
486 
487  unsigned long primColor, secColor, lowColor;
488  lowColor = radialQuanta[secIndex];
489  secColor = secQuanta[secIndex];
490  primColor = primQuanta[primIndex];
491 
492  colorT R, G, B;
493  if (mixIndex == 0) {
494  R = primColor;
495  G = secColor;
496  B = lowColor;
497  }
498  else
499  if (mixIndex == 1) {
500  G = primColor;
501  B = secColor;
502  R = lowColor;
503  }
504  else {
505  B = primColor;
506  R = secColor;
507  G = lowColor;
508  }
509  return oofColor(R, G, B);
510 }
511 
512 
514 {
515  // adopt the storage of the array supplied
516  mDrawStyles.adopt(da);
517 }
518 
519 
522 {
523  // loop over the array to get the new draw style
524  unsigned long NumDrawStyles = mDrawStyles.count();
525  oofColor fore = mDrawStyles.item
526  (mNumDrawStylesProduced%NumDrawStyles).foreColor();
527  // the characteristics to follow are default for the moment
528  // later we will get these from the user supplied structure too
529  oofPattern monoPat(oofPattern::white);
530  oofSymbol* theSymbol;
531  theSymbol = new oofSquareSymbol;
532  oofColor back = oofColor::White;
533  oofPattern colPat = oofPattern::gray;
534 
535  ++mNumDrawStylesProduced; // will start from 0
536  return oofDrawStyle(fore,colPat,monoPat,back,theSymbol, true /* adoptsSymbol */);
537 }
538 
539 
541 {
542 }
543 
544 
545 
546 //---------------------------------------------------------------------------------
547 // * oofSymbol
548 //---------------------------------------------------------------------------------
549 
550 void
551 oofSymbol::draw(short x,short y)
552 {
553  // do any setup here
554  DrawSelf(x,y);
555 }
556 
557 //---------------------------------------------------------------------------------
558 // * oofSimpleSymbol + derivatives
559 //---------------------------------------------------------------------------------
560 
561 
562 oofRect
564 {
565  unsigned short x = getSymbolSizeX();
566  unsigned short y = getSymbolSizeY();
567 
568  oofRect r(0, 0, x, y);
569 
570  return r;
571 }
572 
573 
574 oofSymbol*
576 {
577  return new oofEcsSymbol(*this);
578 }
579 
580 
581 oofSymbol*
583 {
584  return new oofCrossSymbol(*this);
585 }
586 
587 
588 oofSymbol*
590 {
591  return new oofCircleSymbol(*this);
592 }
593 
594 
595 oofSymbol*
597 {
598  return new oofSquareSymbol(*this);
599 }
600 
601 
602 void
603 oofEcsSymbol::DrawSelf(short mXDraw, short mYDraw){
604  unsigned short x = getSymbolSizeX();
605  unsigned short y = getSymbolSizeY();
606 
607 #ifdef _Macintosh
608  ::MoveTo(mXDraw-x/2,mYDraw-y/2);
609  ::LineTo(mXDraw+x/2,mYDraw+y/2);
610  ::MoveTo(mXDraw+x/2,mYDraw-y/2);
611  ::LineTo(mXDraw-x/2,mYDraw+y/2);
612 #elif defined _Windows
613  HDC hCurrdc = oofCurrentDraw::getCurrentDC();
614 
615  ::MoveToEx(hCurrdc, mXDraw-x/2,mYDraw-y/2, NULL);
616  ::LineTo(hCurrdc, mXDraw+x/2,mYDraw+y/2);
617  ::MoveToEx(hCurrdc, mXDraw+x/2,mYDraw-y/2, NULL);
618  ::LineTo(hCurrdc, mXDraw-x/2,mYDraw+y/2);
619 #endif // OS
620 }
621 
622 
623 void
624 oofCrossSymbol::DrawSelf(short mXDraw, short mYDraw){
625  unsigned short x = getSymbolSizeX();
626  unsigned short y = getSymbolSizeY();
627 
628 #ifdef _Macintosh
629  ::MoveTo(mXDraw-x/2,mYDraw);
630  ::LineTo(mXDraw+x/2,mYDraw);
631  ::MoveTo(mXDraw,mYDraw-y/2);
632  ::LineTo(mXDraw,mYDraw+y/2);
633 #elif defined _Windows
634  HDC hCurrdc = oofCurrentDraw::getCurrentDC();
635 
636  ::MoveToEx(hCurrdc, mXDraw-x/2,mYDraw, NULL);
637  ::LineTo(hCurrdc, mXDraw+x/2,mYDraw);
638  ::MoveToEx(hCurrdc, mXDraw,mYDraw-y/2, NULL);
639  ::LineTo(hCurrdc, mXDraw,mYDraw+y/2);
640 #endif // OS
641 }
642 
643 
644 void
645 oofCircleSymbol::DrawSelf(short mXDraw, short mYDraw){
646  unsigned short x = getSymbolSizeX();
647  unsigned short y = getSymbolSizeY();
648 
649  oofRect theRect(mXDraw - x / 2,
650  mYDraw - y / 2,
651  mXDraw + x / 2,
652  mYDraw + y / 2);
653 #ifdef _Macintosh
654  ::FrameOval(theRect);
655 #elif defined _Windows
656  HDC hCurrdc = oofCurrentDraw::getCurrentDC();
657  HBRUSH hOldBr = (HBRUSH)::SelectObject(hCurrdc, ::GetStockObject(NULL_BRUSH));
658 
659  ::Ellipse(hCurrdc, theRect.left, theRect.top, theRect.right, theRect.bottom);
660  ::SelectObject(hCurrdc, hOldBr);
661 #endif // OS
662 }
663 
664 
665 void
666 oofSquareSymbol::DrawSelf(short mXDraw, short mYDraw){
667  unsigned short x = getSymbolSizeX();
668  unsigned short y = getSymbolSizeY();
669 
670  oofRect theRect(mXDraw - x / 2,
671  mYDraw - y / 2,
672  mXDraw + x / 2,
673  mYDraw + y / 2);
674 #ifdef _Macintosh
675  ::FrameRect(theRect);
676 #elif defined _Windows
677  HDC hCurrdc = oofCurrentDraw::getCurrentDC();
678  HBRUSH hOldBr = (HBRUSH)::SelectObject(hCurrdc, ::GetStockObject(NULL_BRUSH));
679 
680  ::Rectangle(hCurrdc, theRect.left, theRect.top, theRect.right, theRect.bottom);
681  ::SelectObject(hCurrdc, hOldBr);
682 #endif // OS
683 }
const oofDrawStyle & item(unsigned long index) const
Definition: oofDStyl.cpp:320
Cross-platform way to specify rectangle with Mac-style setter.
Definition: oofRect.h:39
oofDrawStyleArray mDrawStyles
Definition: oofDStyl.h:154
Draw a hollow square symbol on a line graph.
Definition: oofDStyl.h:239
const oofColor & backColor() const
Definition: oofDStyl.cpp:190
const oofPattern & currentPattern() const
Definition: oofDStyl.cpp:211
virtual ~oofDrawStyleSetSupplied()
Definition: oofDStyl.cpp:540
void setPattern(const oofPattern &)
Definition: oofDStyl.cpp:134
const oofColor & foreColor() const
Definition: oofDStyl.cpp:183
oofDrawStyle(const oofColor &fg=oofColor::Black, const oofPattern &colPat=oofPattern::gray, const oofPattern &monoPat=oofPattern::gray, const oofColor &bg=oofColor::White, oofSymbol *sym=0, bool adoptsSymbol=false)
Definition: oofDStyl.cpp:48
void setJustColorPattern(const oofPattern &)
Definition: oofDStyl.cpp:157
unsigned long count() const
Definition: oofarray.h:126
void append(oofDrawStyle &)
Definition: oofDStyl.cpp:295
void adopt(oofDrawStyleArray *)
adopts the storage of the array passed in, appending to the end of the current storage.
Definition: oofDStyl.cpp:335
oofDrawStyleArray & operator<<(oofDrawStyle *)
Definition: oofDStyl.cpp:304
Abstract base to draw a symbol on a line graph.
Definition: oofDStyl.h:163
virtual oofSymbol * clone() const
Definition: oofDStyl.cpp:575
virtual oofSymbol * clone() const
Definition: oofDStyl.cpp:589
void setJustMonoPattern(const oofPattern &)
Definition: oofDStyl.cpp:170
oofDrawStyleSetSupplied(oofDrawStyleArray *)
Definition: oofDStyl.cpp:513
void deleteAllCells(bool alwaysDeleteStorage=false)
Effectively delete cells by resetting mNextFreeEntry cursor.
Definition: oofarray.cpp:219
#define _Windows
This build is on Windows.
Definition: doxyoof.h:440
const oofPattern & monoPattern() const
Definition: oofDStyl.cpp:204
Draw a circular symbol on a line graph.
Definition: oofDStyl.h:224
static void setStyleToMono()
Definition: oofDStyl.cpp:256
virtual void DrawSelf(short, short)=0
void set(ePattern)
Definition: oofcolor.cpp:67
virtual oofDrawStyle getNextDrawStyle()
Definition: oofDStyl.cpp:521
unsigned short getSymbolSizeY()
temporary method for experimenting with symbol sizes
Definition: oofDStyl.h:172
static bool isMono()
Definition: oofDStyl.cpp:270
static oofColor CalculateColor(unsigned long index)
Definition: oofDStyl.cpp:448
Array of longs which expands automatically as you write to cells.
Definition: oofarray.h:21
unsigned long mNumDrawStylesProduced
Definition: oofDStyl.h:122
Provide cross-platform way to specify patterns.
Definition: oofcolor.h:75
const unsigned int symbolOffsetX
Definition: oofDStyl.cpp:37
const unsigned int symbolHeight
Definition: oofDStyl.cpp:36
Cross-platform color specification class.
Definition: oofcolor.h:123
const oofPattern & colorPattern() const
Definition: oofDStyl.cpp:197
Specify drawing styles used in graphs.
Definition: oofDStyl.h:32
Array of owned oofDrawStyle's adopting them for correct lifetime management.
Definition: oofDStyl.h:86
void append(unsigned long)
Definition: oofarray.cpp:131
unsigned short getSymbolSizeX()
Definition: oofDStyl.h:171
virtual void draw(short, short)
Definition: oofDStyl.cpp:551
virtual oofRect BoundingRect()
Definition: oofDStyl.cpp:563
static void setStyleToColor()
Definition: oofDStyl.cpp:263
void useStyleColors() const
Definition: oofDStyl.cpp:221
unsigned long count() const
Definition: oofDStyl.cpp:348
const unsigned int symbolWidth
Definition: oofDStyl.cpp:35
const oofDrawStyle & operator=(oofDrawStyle &)
Definition: oofDStyl.cpp:113
Draw a cross symbol on a line graph.
Definition: oofDStyl.h:209
virtual oofSymbol * clone() const
Definition: oofDStyl.cpp:582
const unsigned int symbolOffsetY
Definition: oofDStyl.cpp:38
virtual oofDrawStyle getNextDrawStyle()
Definition: oofDStyl.cpp:365
virtual oofSymbol * clone() const
Definition: oofDStyl.cpp:596
Draw a "X" symbol on a line graph.
Definition: oofDStyl.h:195
virtual oofSymbol * clone() const =0
unsigned long value(unsigned long index) const
Definition: oofarray.cpp:243
virtual oofDrawStyle getNextDrawStyle()
Definition: oofDStyl.cpp:360