vtkScalarBarActor.cxx 90.2 KB
Newer Older
1 2 3 4 5
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkScalarBarActor.cxx

6
  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 8
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9

10 11
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12
     PURPOSE.  See the above copyright notice for more information.
13 14 15

=========================================================================*/
#include "vtkScalarBarActor.h"
16
#include "vtkScalarBarActorInternal.h"
17

18 19
#include "vtkCellArray.h"
#include "vtkCellData.h"
20
#include "vtkColor.h"
Mathieu Westphal's avatar
Mathieu Westphal committed
21
#include "vtkColorTransferFunction.h"
22
#include "vtkCoordinate.h"
23 24
#include "vtkFloatArray.h"
#include "vtkImageData.h"
Mathieu Westphal's avatar
Mathieu Westphal committed
25
#include "vtkLookupTable.h"
26
#include "vtkMath.h"
Mathieu Westphal's avatar
Mathieu Westphal committed
27 28
#include "vtkMathTextUtilities.h"
#include "vtkNew.h"
29
#include "vtkObjectFactory.h"
Mathieu Westphal's avatar
Mathieu Westphal committed
30
#include "vtkPointData.h"
31
#include "vtkPolyData.h"
32
#include "vtkPolyDataMapper2D.h"
33
#include "vtkProperty2D.h"
34
#include "vtkRenderWindow.h"
Mathieu Westphal's avatar
Mathieu Westphal committed
35
#include "vtkRenderer.h"
36
#include "vtkScalarsToColors.h"
37 38
#include "vtkSmartPointer.h"
#include "vtkTextActor.h"
39
#include "vtkTextProperty.h"
40
#include "vtkTexture.h"
Ken Martin's avatar
Ken Martin committed
41
#include "vtkTexturedActor2D.h"
42 43
#include "vtkViewport.h"
#include "vtkWindow.h"
44

45 46
#include <vector>
#include <set>
47 48
#include <map>

49
#include <cstdio> // for snprintf
50

51 52
#undef VTK_DBG_LAYOUT

Brad King's avatar
Brad King committed
53
vtkStandardNewMacro(vtkScalarBarActor);
54

Mathieu Westphal's avatar
Mathieu Westphal committed
55 56 57 58 59 60
vtkCxxSetObjectMacro(vtkScalarBarActor, LookupTable, vtkScalarsToColors);
vtkCxxSetObjectMacro(vtkScalarBarActor, AnnotationTextProperty, vtkTextProperty);
vtkCxxSetObjectMacro(vtkScalarBarActor, LabelTextProperty, vtkTextProperty);
vtkCxxSetObjectMacro(vtkScalarBarActor, TitleTextProperty, vtkTextProperty);
vtkCxxSetObjectMacro(vtkScalarBarActor, BackgroundProperty, vtkProperty2D);
vtkCxxSetObjectMacro(vtkScalarBarActor, FrameProperty, vtkProperty2D);
61

62 63
//----------------------------------------------------------------------------
// Instantiate object with 64 maximum colors; 5 labels; %%-#6.3g label
64 65 66 67
// format, no title, and vertical orientation. The initial scalar bar
// size is (0.05 x 0.8) of the viewport size.
vtkScalarBarActor::vtkScalarBarActor()
{
68
  this->P = new vtkScalarBarActorInternal;
69
  this->LookupTable = NULL;
70
  this->Position2Coordinate->SetValue(0.17, 0.8);
71

72
  this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport();
Mathieu Westphal's avatar
Mathieu Westphal committed
73
  this->PositionCoordinate->SetValue(0.82, 0.1);
74

75 76 77
  this->TextPad = 1;
  this->TitleRatio = 0.5;
  this->BarRatio = 0.375;
78 79
  this->MaximumNumberOfColors = 64;
  this->NumberOfLabels = 5;
80
  this->NumberOfLabelsBuilt = 0;
81 82
  this->Orientation = VTK_ORIENT_VERTICAL;
  this->Title = NULL;
83
  this->ComponentTitle = NULL;
84
  this->VerticalTitleSeparation = 0;
85

86 87 88 89 90 91 92
  this->LabelTextProperty = vtkTextProperty::New();
  this->LabelTextProperty->SetFontSize(12);
  this->LabelTextProperty->SetBold(1);
  this->LabelTextProperty->SetItalic(1);
  this->LabelTextProperty->SetShadow(1);
  this->LabelTextProperty->SetFontFamilyToArial();

Mathieu Westphal's avatar
Mathieu Westphal committed
93 94 95 96 97 98 99
  this->AnnotationTextProperty = vtkTextProperty::New();
  this->AnnotationTextProperty->SetFontSize(12);
  this->AnnotationTextProperty->SetBold(1);
  this->AnnotationTextProperty->SetItalic(1);
  this->AnnotationTextProperty->SetShadow(1);
  this->AnnotationTextProperty->SetFontFamilyToArial();

100 101 102
  this->TitleTextProperty = vtkTextProperty::New();
  this->TitleTextProperty->ShallowCopy(this->LabelTextProperty);

103
  this->LabelFormat = new char[8];
Mathieu Westphal's avatar
Mathieu Westphal committed
104
  sprintf(this->LabelFormat, "%s", "%-#6.3g");
105

106
  this->TitleActor = vtkTextActor::New();
107 108
  this->TitleActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);
109

110 111
  this->ScalarBar = vtkPolyData::New();
  this->ScalarBarMapper = vtkPolyDataMapper2D::New();
112
  this->ScalarBarMapper->SetInputData(this->ScalarBar);
113 114
  this->ScalarBarActor = vtkActor2D::New();
  this->ScalarBarActor->SetMapper(this->ScalarBarMapper);
115 116
  this->ScalarBarActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);
117 118 119 120
  this->LastOrigin[0] = 0;
  this->LastOrigin[1] = 0;
  this->LastSize[0] = 0;
  this->LastSize[1] = 0;
121

122
  this->DrawAnnotations = 1;
123
  this->DrawNanAnnotation = 0;
124
  this->AnnotationTextScaling = 0;
125 126 127 128 129 130 131 132 133 134 135
  this->FixedAnnotationLeaderLineColor = 0;
  this->NanAnnotation = 0;
  this->SetNanAnnotation("NaN");
  this->P->NanSwatch = vtkPolyData::New();
  this->P->NanSwatchMapper = vtkPolyDataMapper2D::New();
  this->P->NanSwatchActor = vtkActor2D::New();
  this->P->NanSwatchMapper->SetInputData(this->P->NanSwatch);
  this->P->NanSwatchActor->SetMapper(this->P->NanSwatchMapper);
  this->P->NanSwatchActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);

Mathieu Westphal's avatar
Mathieu Westphal committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
  this->DrawBelowRangeSwatch = false;
  this->BelowRangeAnnotation = 0;
  this->SetBelowRangeAnnotation("Below");
  this->P->BelowRangeSwatch = vtkPolyData::New();
  this->P->BelowRangeSwatchMapper = vtkPolyDataMapper2D::New();
  this->P->BelowRangeSwatchActor = vtkActor2D::New();
  this->P->BelowRangeSwatchMapper->SetInputData(this->P->BelowRangeSwatch);
  this->P->BelowRangeSwatchActor->SetMapper(this->P->BelowRangeSwatchMapper);
  this->P->BelowRangeSwatchActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);

  this->DrawAboveRangeSwatch = false;
  this->AboveRangeAnnotation = 0;
  this->SetAboveRangeAnnotation("Above");
  this->P->AboveRangeSwatch = vtkPolyData::New();
  this->P->AboveRangeSwatchMapper = vtkPolyDataMapper2D::New();
  this->P->AboveRangeSwatchActor = vtkActor2D::New();
  this->P->AboveRangeSwatchMapper->SetInputData(this->P->AboveRangeSwatch);
  this->P->AboveRangeSwatchActor->SetMapper(this->P->AboveRangeSwatchMapper);
  this->P->AboveRangeSwatchActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);

158
  this->AnnotationLeaderPadding = 8.;
159 160 161 162 163 164 165 166 167 168 169 170 171 172
  this->P->AnnotationBoxes = vtkPolyData::New();
  this->P->AnnotationBoxesMapper = vtkPolyDataMapper2D::New();
  this->P->AnnotationBoxesActor = vtkActor2D::New();
  this->P->AnnotationBoxesMapper->SetInputData(this->P->AnnotationBoxes);
  this->P->AnnotationBoxesActor->SetMapper(this->P->AnnotationBoxesMapper);
  this->P->AnnotationBoxesActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);
  this->P->AnnotationLeaders = vtkPolyData::New();
  this->P->AnnotationLeadersMapper = vtkPolyDataMapper2D::New();
  this->P->AnnotationLeadersActor = vtkActor2D::New();
  this->P->AnnotationLeadersMapper->SetInputData(this->P->AnnotationLeaders);
  this->P->AnnotationLeadersActor->SetMapper(this->P->AnnotationLeadersMapper);
  this->P->AnnotationLeadersActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);
173

174 175 176 177 178
  this->P->TitleBox.Posn[0] = 0;
  this->P->TitleBox.Posn[1] = 0;
  this->P->TitleBox.Size[0] = 0;
  this->P->TitleBox.Size[1] = 0;

179 180 181 182
  // If opacity is on, a jail like texture is displayed behind it..

  this->UseOpacity       = 0;
  this->TextureGridWidth = 10.0;
183

184
  this->TexturePolyData = vtkPolyData::New();
185
  vtkPolyDataMapper2D* textureMapper = vtkPolyDataMapper2D::New();
186
  textureMapper->SetInputData(this->TexturePolyData);
Ken Martin's avatar
Ken Martin committed
187
  this->TextureActor = vtkTexturedActor2D::New();
188 189 190 191 192 193 194
  this->TextureActor->SetMapper(textureMapper);
  textureMapper->Delete();
  this->TextureActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);
  vtkFloatArray* tc = vtkFloatArray::New();
  tc->SetNumberOfComponents(2);
  tc->SetNumberOfTuples(4);
Mathieu Westphal's avatar
Mathieu Westphal committed
195 196 197 198
  tc->InsertComponent(0, 0, 0.0);
  tc->InsertComponent(0, 1, 0.0);
  tc->InsertComponent(1, 1, 0.0);
  tc->InsertComponent(3, 0, 0.0);
199 200 201 202
  this->TexturePolyData->GetPointData()->SetTCoords(tc);
  tc->Delete();

  vtkCellArray* polys2 = vtkCellArray::New();
Ken Martin's avatar
Ken Martin committed
203
  polys2->InsertNextCell(4);
204 205 206 207 208 209
  polys2->InsertCellPoint(0);
  polys2->InsertCellPoint(1);
  polys2->InsertCellPoint(2);
  polys2->InsertCellPoint(3);
  polys2->Delete();

210
  vtkProperty2D* imageProperty = vtkProperty2D::New();
211 212 213 214 215 216 217
  imageProperty->SetOpacity(0.08);
  this->TextureActor->SetProperty(imageProperty);
  imageProperty->Delete();

  // Create the default texture. Just a "Jail" like grid

  const unsigned int dim = 128;
218
  vtkImageData* image = vtkImageData::New();
219
  image->SetDimensions(dim, dim, 1);
Berk Geveci's avatar
Berk Geveci committed
220
  image->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
221

222 223
  for (unsigned int y = 0; y < dim; y++)
    {
224 225
    unsigned char* ptr =
      static_cast<unsigned char*>(image->GetScalarPointer(0, y, 0));
226 227
    for (unsigned int x = 0; x < dim; x++)
      {
Mathieu Westphal's avatar
Mathieu Westphal committed
228
      *ptr = ((x == y) || (x == (dim - y - 1))) ? 255 : 0;
229 230 231 232 233
      ++ptr;
      }
    }

  this->Texture = vtkTexture::New();
Mathieu Westphal's avatar
Mathieu Westphal committed
234
  this->Texture->SetInputData(image);
235
  this->Texture->RepeatOn();
Ken Martin's avatar
Ken Martin committed
236
  this->TextureActor->SetTexture(this->Texture);
237
  image->Delete();
238 239 240 241

  // Default text position : Above scalar bar if orientation is horizontal
  //                         Right of scalar bar if orientation is vertical
  this->TextPosition = SucceedScalarBar;
242 243 244

  this->MaximumWidthInPixels = VTK_INT_MAX;
  this->MaximumHeightInPixels = VTK_INT_MAX;
245 246 247 248 249 250 251

  this->BackgroundProperty = vtkProperty2D::New();
  this->FrameProperty = vtkProperty2D::New();

  this->DrawBackground = 0;
  this->Background = vtkPolyData::New();
  this->BackgroundMapper = vtkPolyDataMapper2D::New();
252
  this->BackgroundMapper->SetInputData(this->Background);
253 254
  this->BackgroundActor = vtkActor2D::New();
  this->BackgroundActor->SetMapper(this->BackgroundMapper);
255 256
  this->BackgroundActor->GetPositionCoordinate()
    ->SetReferenceCoordinate(this->PositionCoordinate);
257

258 259 260
#ifdef VTK_DBG_LAYOUT
  this->DrawFrame = 1;
#else // VTK_DBG_LAYOUT
261
  this->DrawFrame = 0;
262
#endif // VTK_DBG_LAYOUT
263 264
  this->Frame = vtkPolyData::New();
  this->FrameMapper = vtkPolyDataMapper2D::New();
265
  this->FrameMapper->SetInputData(this->Frame);
266 267
  this->FrameActor = vtkActor2D::New();
  this->FrameActor->SetMapper(this->FrameMapper);
268 269
  this->FrameActor->GetPositionCoordinate()
    ->SetReferenceCoordinate(this->PositionCoordinate);
270

Mathieu Westphal's avatar
Mathieu Westphal committed
271 272 273
  this->DrawColorBar = 1;
  this->DrawTickLabels = 1;
  this->UnconstrainedFontSize = false;
274 275
}

276
//----------------------------------------------------------------------------
277 278 279
// Release any graphics resources that are being consumed by this actor.
// The parameter window could be used to determine which graphic
// resources to release.
280
void vtkScalarBarActor::ReleaseGraphicsResources(vtkWindow* win)
281 282
{
  this->TitleActor->ReleaseGraphicsResources(win);
283
  if (!this->P->TextActors.empty())
284
    {
285
    vtkScalarBarActorInternal::ActorVector::iterator it;
286
    for (
Mathieu Westphal's avatar
Mathieu Westphal committed
287 288 289
         it = this->P->TextActors.begin();
         it != this->P->TextActors.end();
         ++it)
290
      {
291
      (*it)->ReleaseGraphicsResources(win);
292 293
      }
    }
Mathieu Westphal's avatar
Mathieu Westphal committed
294
  for (size_t i = 0; i < this->P->AnnotationLabels.size(); ++i)
295
    {
296
    this->P->AnnotationLabels[i]->ReleaseGraphicsResources(win);
297
    }
298
  this->ScalarBarActor->ReleaseGraphicsResources(win);
299
  this->P->NanSwatchActor->ReleaseGraphicsResources(win);
Mathieu Westphal's avatar
Mathieu Westphal committed
300 301
  this->P->AboveRangeSwatchActor->ReleaseGraphicsResources(win);
  this->P->BelowRangeSwatchActor->ReleaseGraphicsResources(win);
302 303
  this->P->AnnotationBoxesActor->ReleaseGraphicsResources(win);
  this->P->AnnotationLeadersActor->ReleaseGraphicsResources(win);
304 305
  this->BackgroundActor->ReleaseGraphicsResources(win);
  this->FrameActor->ReleaseGraphicsResources(win);
306
  this->Texture->ReleaseGraphicsResources(win);
307 308
}

309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
//----------------------------------------------------------------------------
void vtkScalarBarActor::GetScalarBarRect(int rect[4], vtkViewport* viewport)
{
  vtkCoordinate *origin = this->ScalarBarActor->GetPositionCoordinate();
  int * vpPos = origin->GetComputedViewportValue(viewport);
  rect[0] = vpPos[0];
  rect[1] = vpPos[1];

  double *bounds = this->ScalarBar->GetBounds();
  rect[0] += static_cast<int>(bounds[0] + 0.5);
  rect[1] += static_cast<int>(bounds[2] + 0.5);
  rect[2] = static_cast<int>(bounds[1] - bounds[0] + 0.5);
  rect[3] = static_cast<int>(bounds[3] - bounds[2] + 0.5);
}

324
//----------------------------------------------------------------------------
325 326
vtkScalarBarActor::~vtkScalarBarActor()
{
327 328
  delete [] this->LabelFormat;
  this->LabelFormat = NULL;
329 330

  this->TitleActor->Delete();
331
  this->SetNanAnnotation(NULL);
Mathieu Westphal's avatar
Mathieu Westphal committed
332 333
  this->SetBelowRangeAnnotation(NULL);
  this->SetAboveRangeAnnotation(NULL);
334

335 336 337
  this->ScalarBar->Delete();
  this->ScalarBarMapper->Delete();
  this->ScalarBarActor->Delete();
Ken Martin's avatar
Ken Martin committed
338

339
  this->P->NanSwatch->Delete();
Mathieu Westphal's avatar
Mathieu Westphal committed
340 341
  this->P->BelowRangeSwatch->Delete();
  this->P->AboveRangeSwatch->Delete();
342
  this->P->NanSwatchMapper->Delete();
Mathieu Westphal's avatar
Mathieu Westphal committed
343 344
  this->P->AboveRangeSwatchMapper->Delete();
  this->P->BelowRangeSwatchMapper->Delete();
345
  this->P->NanSwatchActor->Delete();
Mathieu Westphal's avatar
Mathieu Westphal committed
346 347
  this->P->AboveRangeSwatchActor->Delete();
  this->P->BelowRangeSwatchActor->Delete();
348 349 350 351

  this->P->AnnotationBoxes->Delete();
  this->P->AnnotationBoxesMapper->Delete();
  this->P->AnnotationBoxesActor->Delete();
352

353 354 355
  this->P->AnnotationLeaders->Delete();
  this->P->AnnotationLeadersMapper->Delete();
  this->P->AnnotationLeadersActor->Delete();
356

357 358
  delete [] this->Title;
  this->Title = NULL;
359

360 361
  delete [] this->ComponentTitle;
  this->ComponentTitle = NULL;
362

363
  this->SetLookupTable(NULL);
Mathieu Westphal's avatar
Mathieu Westphal committed
364
  this->SetAnnotationTextProperty(NULL);
365 366
  this->SetLabelTextProperty(NULL);
  this->SetTitleTextProperty(NULL);
367 368 369
  this->Texture->Delete();
  this->TextureActor->Delete();
  this->TexturePolyData->Delete();
370 371 372 373 374 375 376 377
  this->Background->Delete();
  this->BackgroundMapper->Delete();
  this->BackgroundActor->Delete();
  this->Frame->Delete();
  this->FrameMapper->Delete();
  this->FrameActor->Delete();
  this->SetBackgroundProperty(NULL);
  this->SetFrameProperty(NULL);
378
  delete this->P;
379 380
}

381
//----------------------------------------------------------------------------
382
int vtkScalarBarActor::RenderOverlay(vtkViewport* viewport)
Ken Martin's avatar
Ken Martin committed
383
{
384 385 386 387 388
  if (!this->RebuildLayoutIfNeeded(viewport))
    {
    return 0;
    }

389
  int renderedSomething = 0;
390

391 392 393 394 395 396 397 398 399 400 401 402 403
  // Is the viewport's RenderWindow capturing GL2PS-special props? We'll need
  // to handle this specially to get the texture to show up right.
  if (vtkRenderer *renderer = vtkRenderer::SafeDownCast(viewport))
    {
    if (vtkRenderWindow *renderWindow = renderer->GetRenderWindow())
      {
      if (renderWindow->GetCapturingGL2PSSpecialProps())
        {
        renderer->CaptureGL2PSSpecialProp(this);
        }
      }
    }

404
  // Everything is built, just have to render
405 406 407 408
  if (this->DrawBackground)
    {
    renderedSomething += this->BackgroundActor->RenderOverlay(viewport);
    }
409

410
  if (this->UseOpacity && this->DrawColorBar)
411 412 413 414
    {
    renderedSomething += this->TextureActor->RenderOverlay(viewport);
    }

415 416 417
  // Draw either the scalar bar (non-indexed mode) or
  // the annotated value boxes (indexed mode).
  if (!this->LookupTable->GetIndexedLookup())
418
    {
419 420
    if (this->DrawColorBar)
      {
421
      renderedSomething += this->ScalarBarActor->RenderOverlay(viewport);
422
      }
423

424
    if (this->DrawTickLabels)
425
      {
426
      vtkScalarBarActorInternal::ActorVector::iterator it;
427 428 429 430 431 432 433
      for (
           it = this->P->TextActors.begin();
           it != this->P->TextActors.end();
           ++it)
        {
        renderedSomething += (*it)->RenderOverlay(viewport);
        }
434 435
      }
    }
436
  else if (this->DrawColorBar)
437
    {
438 439 440 441 442 443 444 445 446 447
    renderedSomething +=
      this->P->AnnotationBoxesActor->RenderOverlay(viewport);
    }

  if (this->DrawNanAnnotation)
    {
    renderedSomething +=
      this->P->NanSwatchActor->RenderOverlay(viewport);
    }

Mathieu Westphal's avatar
Mathieu Westphal committed
448 449 450 451 452 453 454 455 456 457 458 459
  if (this->DrawBelowRangeSwatch)
    {
    renderedSomething +=
      this->P->BelowRangeSwatchActor->RenderOverlay(viewport);
    }

  if (this->DrawAboveRangeSwatch)
    {
    renderedSomething +=
      this->P->AboveRangeSwatchActor->RenderOverlay(viewport);
    }

460 461 462
  if (this->DrawFrame)
    {
    renderedSomething += this->FrameActor->RenderOverlay(viewport);
463
    }
464

465 466 467 468 469
  if (this->Title != NULL)
    {
    renderedSomething += this->TitleActor->RenderOverlay(viewport);
    }

470
  if (this->DrawAnnotations)
471
    {
472
    if (!this->P->AnnotationLabels.empty())
473 474
      {
      renderedSomething +=
Mathieu Westphal's avatar
Mathieu Westphal committed
475 476
        this->P->AnnotationLeadersActor->RenderOverlay(viewport);
      for (size_t i = 0; i < this->P->AnnotationLabels.size(); ++i)
477 478
        {
        renderedSomething +=
Mathieu Westphal's avatar
Mathieu Westphal committed
479
          this->P->AnnotationLabels[i]->RenderOverlay(viewport);
480
        }
481
      }
482
    }
483

484
  renderedSomething = (renderedSomething > 0)?(1):(0);
485
  return renderedSomething;
Ken Martin's avatar
Ken Martin committed
486 487
}

488
int vtkScalarBarActor::RebuildLayoutIfNeeded(vtkViewport* viewport)
489
{
490
  if (!this->LookupTable)
491
    {
Mathieu Westphal's avatar
Mathieu Westphal committed
492
    vtkWarningMacro(<< "Need a mapper to render a scalar bar");
493
    return 0;
494 495
    }

496 497
  if (!this->TitleTextProperty)
    {
Mathieu Westphal's avatar
Mathieu Westphal committed
498
    vtkErrorMacro(<< "Need title text property to render a scalar bar");
499 500 501 502 503
    return 0;
    }

  if (!this->LabelTextProperty)
    {
Mathieu Westphal's avatar
Mathieu Westphal committed
504 505 506 507 508 509 510
    vtkErrorMacro(<< "Need label text property to render a scalar bar");
    return 0;
    }

  if (!this->AnnotationTextProperty)
    {
    vtkErrorMacro(<< "Need annotation text property to render a scalar bar");
511 512 513
    return 0;
    }

514
  // Check to see whether we have to rebuild everything
515
  int positionsHaveChanged = 0;
516 517
  if (viewport->GetMTime() > this->BuildTime ||
      (viewport->GetVTKWindow() &&
Mathieu Westphal's avatar
Mathieu Westphal committed
518
        viewport->GetVTKWindow()->GetMTime() > this->BuildTime))
519 520 521
    {
    // if the viewport has changed we may - or may not need
    // to rebuild, it depends on if the projected coords chage
522 523
    int size[2];
    int* barOrigin;
524
    barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
525
    size[0] =
526 527
      this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
      barOrigin[0];
528
    size[1] =
529 530
      this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
      barOrigin[1];
531

532 533
    // Check if we have bounds on the maximum size
    size[0] = size[0] > this->MaximumWidthInPixels
Mathieu Westphal's avatar
Mathieu Westphal committed
534
      ? this->MaximumWidthInPixels : size[0];
535
    size[1] = size[1] > this->MaximumHeightInPixels
Mathieu Westphal's avatar
Mathieu Westphal committed
536
      ? this->MaximumHeightInPixels : size[1];
537

538
    if (this->LastSize[0] != size[0] ||
539
        this->LastSize[1] != size[1] ||
540
        this->LastOrigin[0] != barOrigin[0] ||
541
        this->LastOrigin[1] != barOrigin[1])
542
      {
543
      positionsHaveChanged = 1;
544 545
      }
    }
546

547
  // Check to see whether we have to rebuild everything
548
  if (positionsHaveChanged ||
549
      this->GetMTime() > this->BuildTime ||
550
      this->LookupTable->GetMTime() > this->BuildTime ||
Mathieu Westphal's avatar
Mathieu Westphal committed
551
      this->AnnotationTextProperty->GetMTime() > this->BuildTime ||
552
      this->LabelTextProperty->GetMTime() > this->BuildTime ||
553 554 555 556
      this->TitleTextProperty->GetMTime() > this->BuildTime ||
      this->BackgroundProperty->GetMTime() > this->BuildTime ||
      this->FrameProperty->GetMTime() > this->BuildTime)

557
    {
558
    this->RebuildLayout(viewport);
559
    }
560 561 562 563 564 565 566 567 568 569 570 571
  return 1;
}

//----------------------------------------------------------------------------
int vtkScalarBarActor::RenderOpaqueGeometry(vtkViewport* viewport)
{
  if (!this->RebuildLayoutIfNeeded(viewport))
    {
    return 0;
    }

  int renderedSomething = 0;
572 573

  // Everything is built, just have to render
Jim Miller's avatar
Jim Miller committed
574 575
  if (this->Title != NULL)
    {
576 577
    renderedSomething +=
      this->TitleActor->RenderOpaqueGeometry(viewport);
Jim Miller's avatar
Jim Miller committed
578
    }
579 580
  // Draw either the scalar bar (non-indexed mode) or
  // the annotated value boxes (indexed mode).
Mathieu Westphal's avatar
Mathieu Westphal committed
581
  if (!this->LookupTable->GetIndexedLookup())
Jim Miller's avatar
Jim Miller committed
582
    {
583 584
    if (this->DrawColorBar)
      {
585 586
      renderedSomething +=
        this->ScalarBarActor->RenderOpaqueGeometry(viewport);
587
      }
588
    vtkScalarBarActorInternal::ActorVector::iterator ait;
589
    for (
Mathieu Westphal's avatar
Mathieu Westphal committed
590 591 592
         ait = this->P->TextActors.begin();
         ait != this->P->TextActors.end();
         ++ait)
593
      {
594
      renderedSomething += (*ait)->RenderOpaqueGeometry(viewport);
595 596 597 598
      }
    }
  else
    {
599 600
    if (this->DrawColorBar)
      {
601
      renderedSomething +=
Mathieu Westphal's avatar
Mathieu Westphal committed
602
        this->P->AnnotationBoxesActor->RenderOpaqueGeometry(viewport);
603 604 605 606 607 608 609 610 611
      }
    }

  if (this->DrawNanAnnotation)
    {
    renderedSomething +=
      this->P->NanSwatchActor->RenderOpaqueGeometry(viewport);
    }

Mathieu Westphal's avatar
Mathieu Westphal committed
612 613 614 615 616 617 618 619 620 621 622 623
  if (this->DrawBelowRangeSwatch)
    {
    renderedSomething +=
      this->P->BelowRangeSwatchActor->RenderOpaqueGeometry(viewport);
    }

  if (this->DrawAboveRangeSwatch)
    {
    renderedSomething +=
      this->P->AboveRangeSwatchActor->RenderOpaqueGeometry(viewport);
    }

624
  // Draw the annotation leaders and labels
Mathieu Westphal's avatar
Mathieu Westphal committed
625
  if (this->DrawAnnotations)
626
    {
627
    if (!this->P->AnnotationLabels.empty())
628 629
      {
      renderedSomething +=
Mathieu Westphal's avatar
Mathieu Westphal committed
630 631
        this->P->AnnotationLeadersActor->RenderOpaqueGeometry(viewport);
      for (size_t i = 0; i < this->P->AnnotationLabels.size(); ++i)
632 633
        {
        renderedSomething +=
Mathieu Westphal's avatar
Mathieu Westphal committed
634
          this->P->AnnotationLabels[i]->RenderOpaqueGeometry(viewport);
635
        }
636
      }
Jim Miller's avatar
Jim Miller committed
637
    }
638 639 640 641

  renderedSomething = (renderedSomething > 0)?(1):(0);

  return renderedSomething;
642 643
}

644 645 646 647
//-----------------------------------------------------------------------------
// Description:
// Does this prop have some translucent polygonal geometry?
int vtkScalarBarActor::HasTranslucentPolygonalGeometry()
648 649 650 651
{ // TODO: Handle case when IndexedLookup is true and any colors in the palette
  // have an alpha value, as the color swatches drawn by
  // this->P->AnnotationBoxesActor have 1 translucent triangle for each
  // alpha-swatch.
652 653 654
  return 0;
}

655
//----------------------------------------------------------------------------
656
void vtkScalarBarActor::PrintSelf(ostream& os, vtkIndent indent)
657
{
Mathieu Westphal's avatar
Mathieu Westphal committed
658
  this->Superclass::PrintSelf(os, indent);
659

Mathieu Westphal's avatar
Mathieu Westphal committed
660
  if (this->LookupTable)
661 662
    {
    os << indent << "Lookup Table:\n";
Mathieu Westphal's avatar
Mathieu Westphal committed
663
    this->LookupTable->PrintSelf(os, indent.GetNextIndent());
664 665 666 667 668 669
    }
  else
    {
    os << indent << "Lookup Table: (none)\n";
    }

670 671 672
  if (this->TitleTextProperty)
    {
    os << indent << "Title Text Property:\n";
Mathieu Westphal's avatar
Mathieu Westphal committed
673
    this->TitleTextProperty->PrintSelf(os, indent.GetNextIndent());
674 675 676 677 678 679 680 681 682
    }
  else
    {
    os << indent << "Title Text Property: (none)\n";
    }

  if (this->LabelTextProperty)
    {
    os << indent << "Label Text Property:\n";
Mathieu Westphal's avatar
Mathieu Westphal committed
683
    this->LabelTextProperty->PrintSelf(os, indent.GetNextIndent());
684 685 686 687 688 689
    }
  else
    {
    os << indent << "Label Text Property: (none)\n";
    }

Mathieu Westphal's avatar
Mathieu Westphal committed
690 691 692 693 694 695 696 697 698 699
  if (this->AnnotationTextProperty)
    {
    os << indent << "Annotation Text Property:\n";
    this->AnnotationTextProperty->PrintSelf(os, indent.GetNextIndent());
    }
  else
    {
    os << indent << "Annotation Text Property: (none)\n";
    }

700
  os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n";
701 702
  os << indent << "ComponentTitle: "
    << (this->ComponentTitle ? this->ComponentTitle : "(none)") << "\n";
703
  os << indent << "Maximum Number Of Colors: "
Mathieu Westphal's avatar
Mathieu Westphal committed
704
    << this->MaximumNumberOfColors << "\n";
705
  os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n";
706
  os << indent << "Number Of Labels Built: " << this->NumberOfLabelsBuilt << "\n";
707 708

  os << indent << "Orientation: ";
Mathieu Westphal's avatar
Mathieu Westphal committed
709
  if (this->Orientation == VTK_ORIENT_HORIZONTAL)
Jim Miller's avatar
Jim Miller committed
710 711 712 713 714 715 716
    {
    os << "Horizontal\n";
    }
  else
    {
    os << "Vertical\n";
    }
717 718

  os << indent << "Label Format: " << this->LabelFormat << "\n";
719 720 721 722
  os << indent << "UseOpacity: " << this->UseOpacity << "\n";
  if (this->UseOpacity)
    {
    os << indent << "TextureGridWidth: " << this->TextureGridWidth << "\n";
Karthik Krishnan's avatar
Karthik Krishnan committed
723 724
    os << indent << "TextureActor:\n";
    this->TextureActor->PrintSelf(os, indent.GetNextIndent());
725
    }
726 727 728 729 730 731 732 733
  if (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
    {
    os << indent << "TextPosition: PrecedeScalarBar\n";
    }
  else
    {
    os << indent << "TextPosition: SucceedScalarBar\n";
    }
734

735
  os << indent << "MaximumWidthInPixels: "
Mathieu Westphal's avatar
Mathieu Westphal committed
736
    << this->MaximumWidthInPixels << endl;
737
  os << indent << "MaximumHeightInPixels: "
Mathieu Westphal's avatar
Mathieu Westphal committed
738
    << this->MaximumHeightInPixels << endl;
739

740 741
  os << indent << "DrawAnnotations: "
    << this->DrawAnnotations << endl;
742 743 744 745
  os << indent << "DrawNanAnnotation: "
    << this->DrawNanAnnotation << endl;
  os << indent << "NanAnnotation: "
    << (this->NanAnnotation ? this->NanAnnotation : "(none)") << endl;
746 747
  os << indent << "AnnotationLeaderPadding: "
    << this->AnnotationLeaderPadding << endl;
748 749
  os << indent << "AnnotationTextScaling: "
    << this->AnnotationTextScaling << endl;
750 751
  os << indent << "VerticalTitleSeparation: "
    << VerticalTitleSeparation << endl;
752

Mathieu Westphal's avatar
Mathieu Westphal committed
753 754 755 756 757 758 759 760 761 762
  os << indent << "DrawBelowRangeSwatch: "
    << this->DrawBelowRangeSwatch << endl;
  os << indent << "BelowRangeAnnotation: "
    << (this->BelowRangeAnnotation ? this->BelowRangeAnnotation : "(none)") << endl;

  os << indent << "DrawAboveRangeSwatch: "
    << this->DrawAboveRangeSwatch << endl;
  os << indent << "AboveRangeAnnotation: "
    << (this->AboveRangeAnnotation ? this->AboveRangeAnnotation : "(none)") << endl;

763 764
  os << indent << "DrawBackground: " << this->DrawBackground << "\n";
  os << indent << "Background Property:\n";
Mathieu Westphal's avatar
Mathieu Westphal committed
765
  this->BackgroundProperty->PrintSelf(os, indent.GetNextIndent());
766 767
  os << indent << "DrawFrame: " << this->DrawFrame << "\n";
  os << indent << "Frame Property:\n";
Mathieu Westphal's avatar
Mathieu Westphal committed
768
  this->FrameProperty->PrintSelf(os, indent.GetNextIndent());
769
}
Ken Martin's avatar
Ken Martin committed
770

771
//----------------------------------------------------------------------------
772
void vtkScalarBarActor::ShallowCopy(vtkProp* prop)
Will Schroeder's avatar
Will Schroeder committed
773
{
774
  vtkScalarBarActor* a = vtkScalarBarActor::SafeDownCast(prop);
Mathieu Westphal's avatar
Mathieu Westphal committed
775
  if (a != NULL)
Will Schroeder's avatar
Will Schroeder committed
776 777 778 779 780
    {
    this->SetPosition2(a->GetPosition2());
    this->SetLookupTable(a->GetLookupTable());
    this->SetMaximumNumberOfColors(a->GetMaximumNumberOfColors());
    this->SetOrientation(a->GetOrientation());
Mathieu Westphal's avatar
Mathieu Westphal committed
781
    this->SetAnnotationTextProperty(a->GetAnnotationTextProperty());
782 783
    this->SetLabelTextProperty(a->GetLabelTextProperty());
    this->SetTitleTextProperty(a->GetTitleTextProperty());
Will Schroeder's avatar
Will Schroeder committed
784 785 786
    this->SetLabelFormat(a->GetLabelFormat());
    this->SetTitle(a->GetTitle());
    this->GetPositionCoordinate()->SetCoordinateSystem(
787
      a->GetPositionCoordinate()->GetCoordinateSystem());
Will Schroeder's avatar
Will Schroeder committed
788 789 790
    this->GetPositionCoordinate()->SetValue(
      a->GetPositionCoordinate()->GetValue());
    this->GetPosition2Coordinate()->SetCoordinateSystem(
791
      a->GetPosition2Coordinate()->GetCoordinateSystem());
Will Schroeder's avatar
Will Schroeder committed
792 793
    this->GetPosition2Coordinate()->SetValue(
      a->GetPosition2Coordinate()->GetValue());
794 795 796 797
    this->SetDrawBackground(a->GetDrawBackground());
    this->SetBackgroundProperty(a->GetBackgroundProperty());
    this->SetDrawFrame(a->GetDrawFrame());
    this->SetFrameProperty(a->GetFrameProperty());
Will Schroeder's avatar
Will Schroeder committed
798 799 800 801 802
    }

  // Now do superclass
  this->vtkActor2D::ShallowCopy(prop);
}
Ken Martin's avatar
Ken Martin committed
803

804
//----------------------------------------------------------------------------
805
void vtkScalarBarActor::RebuildLayout(vtkViewport* viewport)
Ken Martin's avatar
Ken Martin committed
806
{
Mathieu Westphal's avatar
Mathieu Westphal committed
807
  vtkDebugMacro(<< "Rebuilding subobjects");
808

809 810
  this->P->Viewport = viewport;
  this->FreeLayoutStorage();
811

812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
  // Permute indices used to measure width and height
  // so that thickness and length according to the orientation
  // of the scalar bar instead.
  if (this->Orientation == VTK_ORIENT_VERTICAL)
    {
    this->P->TL[0] = 0;
    this->P->TL[1] = 1;
    }
  else
    {
    this->P->TL[0] = 1;
    this->P->TL[1] = 0;
    }
  this->P->NumNotes = this->LookupTable->GetNumberOfAnnotatedValues();

  // Warning: The order of these calls is extremely important
  // as each updates members of this->P used by later methods!
  this->ComputeFrame();
  this->ComputeScalarBarThickness();
Mathieu Westphal's avatar
Mathieu Westphal committed
831
  this->ComputeSwatchPad();
832
  this->LayoutNanSwatch();
Mathieu Westphal's avatar
Mathieu Westphal committed
833 834 835
  this->LayoutBelowRangeSwatch();
  this->LayoutAboveRangeSwatch();

836 837 838
  this->PrepareTitleText();
  this->LayoutTitle();
  this->ComputeScalarBarLength();
Mathieu Westphal's avatar
Mathieu Westphal committed
839 840 841

  this->LayoutAboveRangeSwatchPosn();

842
  this->LayoutTicks();
Mathieu Westphal's avatar
Mathieu Westphal committed
843

844 845
  this->LayoutAnnotations();

Mathieu Westphal's avatar
Mathieu Westphal committed
846 847 848 849 850
  if (this->UnconstrainedFontSize)
    {
    this->LayoutForUnconstrainedFont();
    }

851 852 853 854 855 856 857 858 859
  // Now generate/configure the VTK datasets and actors that
  // illustrate the scalar bar when rendered using the
  // layout computed above.
  this->ConfigureAnnotations();
  this->ConfigureFrame();
  this->ConfigureScalarBar();
  this->ConfigureTitle();
  this->ConfigureTicks();
  this->ConfigureNanSwatch();
Mathieu Westphal's avatar
Mathieu Westphal committed
860 861
  this->ConfigureAboveBelowRangeSwatch(false);
  this->ConfigureAboveBelowRangeSwatch(true);
862 863 864
#ifdef VTK_DBG_LAYOUT
  this->DrawBoxes();
#endif // VTK_DBG_LAYOUT
865
  this->BuildTime.Modified();
866 867
}

Mathieu Westphal's avatar
Mathieu Westphal committed
868
namespace
869
{
Mathieu Westphal's avatar
Mathieu Westphal committed
870 871
void AddBox(vtkPoints* pts, vtkCellArray* lines, vtkScalarBarBox& box, int tl[2])
  {
872 873 874
  vtkIdType pid[5];
  pid[0] = pts->InsertNextPoint(box.Posn[0], box.Posn[1], 0.);
  pid[1] = pts->InsertNextPoint(box.Posn[0] + box.Size[tl[0]], box.Posn[1], 0.);
Mathieu Westphal's avatar
Mathieu Westphal committed
875 876
  pid[2] = pts->InsertNextPoint(box.Posn[0] + box.Size[tl[0]], box.Posn[1] +
    box.Size[tl[1]], 0.);
877 878 879 880 881 882 883
  pid[3] = pts->InsertNextPoint(box.Posn[0], box.Posn[1] + box.Size[tl[1]], 0.);

  pid[4] = pid[0];
  for (int i = 0; i < 4; ++i)
    {
    lines->InsertNextCell(2, pid + i);
    }
Mathieu Westphal's avatar
Mathieu Westphal committed
884
  }
885 886 887 888 889 890 891 892 893 894 895 896 897 898
}

void vtkScalarBarActor::DrawBoxes()
{
  vtkPoints* pts = this->Frame->GetPoints();
  vtkCellArray* lines = this->Frame->GetLines();

  AddBox(pts, lines, this->P->ScalarBarBox, this->P->TL);
  AddBox(pts, lines, this->P->NanBox, this->P->TL);
  AddBox(pts, lines, this->P->TitleBox, this->P->TL);
  if (this->NumberOfLabels > 0)
    {
    AddBox(pts, lines, this->P->TickBox, this->P->TL);
    }
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
}

//----------------------------------------------------------------------------
void vtkScalarBarActor::ComputeFrame()
{
  // get the viewport size in display coordinates
  int* p0;
  int* p1;
  int size[2];
  p0 = this->PositionCoordinate->GetComputedViewportValue(this->P->Viewport);
  p1 = this->Position2Coordinate->GetComputedViewportValue(this->P->Viewport);
  for (int i = 0; i < 2; ++i)
    {
    //this->P->Frame.Posn[i] = p0[i];
    this->P->Frame.Posn[i] = 0; // Translate the frame's coordinate system to p0
    size[i] = p1[i] - p0[i];
    }

  // Check if we have bounds on the maximum size
  size[0] = size[0] > this->MaximumWidthInPixels
Mathieu Westphal's avatar
Mathieu Westphal committed
919
    ? this->MaximumWidthInPixels : size[0];
920
  size[1] = size[1] > this->MaximumHeightInPixels
Mathieu Westphal's avatar
Mathieu Westphal committed
921
    ? this->MaximumHeightInPixels : size[1];
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939

  for (int i = 0; i < 2; ++i)
    {
    this->P->Frame.Size[i] = size[this->P->TL[i]];
    }

  this->LastOrigin[0] = p0[0];
  this->LastOrigin[1] = p0[1];
  this->LastSize[0] = size[0];
  this->LastSize[1] = size[1];
}

//----------------------------------------------------------------------------
void vtkScalarBarActor::ComputeScalarBarThickness()
{
  // We do not set Size[1] (length), since the title bounds may encroach
  // on it in the vertical orientation.
  this->P->ScalarBarBox.Size[0] =
940
    static_cast<int>(ceil(this->P->Frame.Size[0] * this->BarRatio));
941 942 943 944 945 946 947 948 949 950 951 952 953 954

  // The lower-left corner of the scalar bar may be estimated here
  // as identical to the Frame position in one or both coordinates,
  // depending on whether tick marks should precede the scalar bar or
  // not and on the orientation.
  //
  // It will be altered later in this->LayoutTicks to account
  // for the half-height/width of tick labels.
  this->P->ScalarBarBox.Posn = this->P->Frame.Posn;
  if (this->TextPosition == PrecedeScalarBar)
    {
    this->P->ScalarBarBox.Posn[this->P->TL[0]] +=
      this->P->Frame.Size[0] - this->P->ScalarBarBox.Size[0];
    }
955 956

  // Now knock the thickness down and nudge the bar so the bar doesn't hug the frame.
957 958 959 960 961
  double nudge = this->P->ScalarBarBox.Size[0] / 8.;
  if (nudge > this->TextPad)
    {
    nudge = this->TextPad;
    }
Mathieu Westphal's avatar
Mathieu Westphal committed
962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980
  this->P->ScalarBarBox.Size[0] =
    static_cast<int>(this->P->ScalarBarBox.Size[0] - nudge);
  this->P->ScalarBarBox.Posn[this->P->TL[0]] =
    static_cast<int>(this->P->ScalarBarBox.Posn[this->P->TL[0]] +
      (nudge * (this->TextPosition == PrecedeScalarBar ? -1 : 1)));
}

//----------------------------------------------------------------------------
void vtkScalarBarActor::ComputeSwatchPad()
{
  if (this->P->NumNotes)
    {
    this->P->SwatchPad = this->P->Frame.Size[1] / this->P->NumNotes > 16. ?
      4. : (this->P->Frame.Size[1] / this->P->NumNotes / 4.);
    }
  else
    {
    this->P->SwatchPad = 4.;
    }
981 982 983 984 985 986 987 988 989 990 991
}

//----------------------------------------------------------------------------
void vtkScalarBarActor::LayoutNanSwatch()
{
  // We don't have ScalarBarBox.Size[1] set yet; use the frame width instead.
  this->P->NanSwatchSize = static_cast<double>(
    this->P->ScalarBarBox.Size[0] > this->P->Frame.Size[1] / 4 ?
    this->P->Frame.Size[1] / 4 : this->P->ScalarBarBox.Size[0]);
  if (this->P->NanSwatchSize < 4 && this->P->Frame.Size[1] > 16)
    {
Mathieu Westphal's avatar
Mathieu Westphal committed
992
    this->P->NanSwatchSize = 4;
993
    }
Mathieu Westphal's avatar
Mathieu Westphal committed
994
  if (!this->DrawNanAnnotation)
995
    {
Mathieu Westphal's avatar
Mathieu Westphal committed
996
    this->P->NanSwatchSize = 0;
997 998 999 1000 1001
    }

  if (this->Orientation == VTK_ORIENT_VERTICAL)
    {
    this->P->NanBox.Posn[0] = this->P->ScalarBarBox.Posn[0];
1002
    this->P->NanBox.Posn[1] = this->P->Frame.Posn[1] + this->TextPad;
1003 1004
    this->P->ScalarBarBox.Posn[1] = static_cast<int>(this->P->ScalarBarBox.Posn[1] +
      (this->P->NanSwatchSize + this->P->SwatchPad));
1005 1006 1007 1008
    }
  else // HORIZONTAL
    {
    this->P->NanBox.Posn = this->P->ScalarBarBox.Posn;
Mathieu Westphal's avatar
Mathieu Westphal committed
1009 1010 1011
    this->P->NanBox.Posn[this->P->TL[1]] =
      static_cast<int>(this->P->NanBox.Posn[this->P->TL[1]] +
        (this->P->Frame.Size[1] - this->P->NanSwatchSize));
1012 1013
    }
  this->P->NanBox.Size[0] = this->P->ScalarBarBox.Size[0];
1014
  this->P->NanBox.Size[1] = static_cast<int>(this->P->NanSwatchSize);
1015 1016 1017 1018
  if (this->P->NanBox.Size[1] > 2 * this->TextPad)
    {
    this->P->NanBox.Size[1] -= this->TextPad;
    }
1019 1020
}

Mathieu Westphal's avatar
Mathieu Westphal committed
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
//----------------------------------------------------------------------------
void vtkScalarBarActor::LayoutBelowRangeSwatch()
{
  // We don't have ScalarBarBox.Size[1] set yet; use the frame width instead.
  this->P->BelowRangeSwatchSize = static_cast<double>(
    this->P->ScalarBarBox.Size[0] > this->P->Frame.Size[1] / 4 ?
    this->P->Frame.Size[1] / 4 : this->P->ScalarBarBox.Size[0]);
  if (this->P->BelowRangeSwatchSize < 4 && this->P->Frame.Size[1] > 16)
    {
    this->P->BelowRangeSwatchSize = 4;
    }
  if (!this->DrawBelowRangeSwatch)
    {
    this->P->BelowRangeSwatchSize = 0;
    }

  if (this->Orientation == VTK_ORIENT_VERTICAL)
    {
    this->P->BelowRangeSwatchBox.Posn[0] = this->P->ScalarBarBox.Posn[0];
    this->P->BelowRangeSwatchBox.Posn[1] = this->P->Frame.Posn[1] + this->TextPad;

    // move away because of nan annotation
    if (this->DrawNanAnnotation)
      {
      this->P->BelowRangeSwatchBox.Posn[1] =
        static_cast<int>(this->P->BelowRangeSwatchBox.Posn[1] +
          (this->P->NanBox.Size[1] + this->P->SwatchPad));
      }
    this->P->ScalarBarBox.Posn[1] = static_cast<int>(this->P->ScalarBarBox.Posn[1] +
      this->P->BelowRangeSwatchSize);
    }
  else // HORIZONTAL
    {
    this->P->BelowRangeSwatchBox.Posn = this->P->ScalarBarBox.Posn;
    }

  this->P->BelowRangeSwatchBox.Size[0] = this->P->ScalarBarBox.Size[0];
  this->P->BelowRangeSwatchBox.Size[1] =
    static_cast<int>(this->P->BelowRangeSwatchSize);
  if (this->P->BelowRangeSwatchBox.Size[1] > 2 * this->TextPad)
    {
    this->P->BelowRangeSwatchBox.Size[1] -= this->TextPad;
    }
}

//----------------------------------------------------------------------------
void vtkScalarBarActor::LayoutAboveRangeSwatch()
{
  // We don't have ScalarBarBox.Size[1] set yet; use the frame width instead.
  this->P->AboveRangeSwatchSize = static_cast<double>(
    this->P->ScalarBarBox.Size[0] > this->P->Frame.Size[1] / 4 ?
    this->P->Frame.Size[1] / 4 : this->P->ScalarBarBox.Size[0]);
  if (this->P->AboveRangeSwatchSize < 4 && this->P->Frame.Size[1] > 16)
    {
    this->P->AboveRangeSwatchSize = 4;
    }
  if (!this->DrawAboveRangeSwatch)
    {
    this->P->AboveRangeSwatchSize = 0;
    }
}

//----------------------------------------------------------------------------
void vtkScalarBarActor::LayoutAboveRangeSwatchPosn()
{
  if (this->Orientation == VTK_ORIENT_VERTICAL)
    {
    this->P->AboveRangeSwatchBox.Posn[0] = this->P->ScalarBarBox.Posn[0];
    this->P->AboveRangeSwatchBox.Posn[1] =
      this->P->Frame.Posn[1] + this->TextPad + this->P->ScalarBarBox.Size[1] +
      this->P->SwatchPad;

    if (this->DrawNanAnnotation)
      {
      this->P->AboveRangeSwatchBox.Posn[1] =
        static_cast<int>(this->P->AboveRangeSwatchBox.Posn[1] +
                         this->P->SwatchPad +
                         this->P->NanBox.Size[1]);
      }

    if (this->DrawBelowRangeSwatch)
      {
      this->P->AboveRangeSwatchBox.Posn[1] =
        static_cast<int>(this->P->AboveRangeSwatchBox.Posn[1] +
                         this->P->SwatchPad +
                         this->P->BelowRangeSwatchBox.Size[1]);
      }
    }
  else // HORIZONTAL
    {
    this->P->AboveRangeSwatchBox.Posn = this->P->ScalarBarBox.Posn;
    this->P->AboveRangeSwatchBox.Posn[this->P->TL[1]] =
      static_cast<int>(this->P->AboveRangeSwatchBox.Posn[this->P->TL[1]] +
        (this->P->Frame.Size[1] - this->P->AboveRangeSwatchSize));

    if (this->DrawNanAnnotation)
      {
      this->P->AboveRangeSwatchBox.Posn[this->P->TL[1]] =
        static_cast<int>(this->P->AboveRangeSwatchBox.Posn[this->P->TL[1]] -
          (this->P->NanBox.Size[this->P->TL[1]] + this->P->SwatchPad));
      }
    }
  this->P->AboveRangeSwatchBox.Size[0] = this->P->ScalarBarBox.Size[0];
  this->P->AboveRangeSwatchBox.Size[1] =
    static_cast<int>(this->P->AboveRangeSwatchSize);
  if (this->P->AboveRangeSwatchBox.Size[1] > 2 * this->TextPad)
    {
    this->P->AboveRangeSwatchBox.Size[1] -= this->TextPad;
    }
}

1132 1133 1134 1135 1136 1137 1138 1139 1140
//----------------------------------------------------------------------------
void vtkScalarBarActor::PrepareTitleText()
{
  // Update actor with the latest title/subtitle
  if (this->ComponentTitle && strlen(this->ComponentTitle) > 0)
    {
    //need to account for a space between title & component and null term
    char* combinedTitle =
      new char[strlen(this->Title) + strlen(this->ComponentTitle) + 2];
Mathieu Westphal's avatar
Mathieu Westphal committed
1141
    strcpy(combinedTitle, this->Title);
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
    strcat(combinedTitle, " ");
    strcat(combinedTitle, this->ComponentTitle);
    this->TitleActor->SetInput(combinedTitle);
    delete [] combinedTitle;
    }
  else
    {
    this->TitleActor->SetInput(this->Title);
    }

  if (this->TitleTextProperty->GetMTime() > this->BuildTime)
    {
    // Shallow copy here so that the size of the title prop is not affected
    // by the automatic adjustment of its text mapper's size (i.e. its
    // mapper's text property is identical except for the font size
    // which will be modified later). This allows text actors to
    // share the same text property, and in that case specifically allows
    // the title and label text prop to be the same.
    this->TitleActor->GetTextProperty()->ShallowCopy(this->TitleTextProperty);
    this->TitleActor->GetTextProperty()->SetJustificationToCentered();
    this->TitleActor->GetTextProperty()->SetVerticalJustification(
      this->TextPosition == PrecedeScalarBar ? VTK_TEXT_BOTTOM : VTK_TEXT_TOP);
    }
}

//----------------------------------------------------------------------------
void vtkScalarBarActor::LayoutTitle()
{
  if (this->Title == NULL || !strlen(this->Title))
    {
Mathieu Westphal's avatar
Mathieu Westphal committed
1172 1173
    this->P->TitleBox.Posn = vtkTuple<int, 2>(0.);
    this->P->TitleBox.Size = vtkTuple<int, 2>(0.);
1174 1175 1176 1177 1178
    return;
    }

  int targetWidth, targetHeight;
  // Title spans entire width of frame at top, regardless of orientation.
Mathieu Westphal's avatar
Mathieu Westphal committed
1179 1180
  targetWidth = static_cast<int>(this->P->Frame.Size[this->P->TL[0]]) - 2 *
    this->TextPad;
1181 1182 1183 1184 1185 1186 1187 1188 1189
  // Height is either: at most half the frame height or
  // a fixed portion of the frame remaining after subtracting the
  // scalar bar's thickness.
  //
  // When laid out horizontally, ticks share vertical space with title.
  // We want the title to be larger (18pt vs 14pt).
  targetHeight = static_cast<int>((
    this->Orientation == VTK_ORIENT_VERTICAL ||
    this->LookupTable->GetIndexedLookup()) ?
Mathieu Westphal's avatar
Mathieu Westphal committed
1190 1191 1192 1193 1194
      ceil(this->P->Frame.Size[this->P->TL[1]] / 2. - this->TextPad) :
      (this->P->Frame.Size[0] - this->P->ScalarBarBox.Size[0] -
       (this->TextPosition == SucceedScalarBar ?
         this->P->ScalarBarBox.Posn[this->P->TL[0]] : 0) - this->TextPad) *
      this->TitleRatio);
1195

Mathieu Westphal's avatar
Mathieu Westphal committed
1196 1197 1198 1199 1200 1201 1202 1203 1204 1205
  if (this->UnconstrainedFontSize)
    {
    this->TitleActor->GetTextProperty()->SetFontSize(
      this->TitleTextProperty->GetFontSize());
    }
  else
    {
    this->TitleActor->SetConstrainedFontSize(
      this->P->Viewport, targetWidth, targetHeight);
    }
1206 1207 1208 1209 1210

  // Now fetch the actual size from the actor and use it to
  // update the box size and position.
  double titleSize[2] = {0, 0};
  this->TitleActor->GetSize(this->P->Viewport, titleSize);
1211
  this->TitleActor->GetTextProperty()->SetVerticalJustificationToTop();
1212 1213 1214 1215 1216
  for (int i = 0; i < 2; ++i)
    {
    this->P->TitleBox.Size[this->P->TL[i]] =
      static_cast<int>(ceil(titleSize[i]));
    }
1217

1218 1219 1220 1221
  this->P->TitleBox.Posn[0] =
    this->P->Frame.Posn[0] +
    (this->P->Frame.Size[this->P->TL[0]] - titleSize[0]) / 2;
  this->P->TitleBox.Posn[1] =
1222
    static_cast<int>(this->P->Frame.Posn[1] + this->P->Frame.Size[this->P->TL[1]]);
1223
  if (
Mathieu Westphal's avatar
Mathieu Westphal committed
1224 1225
      this->Orientation == VTK_ORIENT_VERTICAL ||
      this->TextPosition == vtkScalarBarActor::SucceedScalarBar)
1226
    {
1227
    this->P->TitleBox.Posn[1] -= this->P->TitleBox.Size[this->P->TL[1]] +
Mathieu Westphal's avatar
Mathieu Westphal committed
1228
      this->TextPad + static_cast<int>(this->FrameProperty->GetLineWidth());
1229 1230 1231
    }
  else
    {
1232
    this->P->TitleBox.Posn[1] = this->P->Frame.Posn[1] + this->TextPad -
Mathieu Westphal's avatar
Mathieu Westphal committed
1233
      static_cast<int>(this->FrameProperty->GetLineWidth());
1234 1235 1236 1237 1238 1239 1240 1241
    }
}

//-----------------------------------------------------------------------------
void vtkScalarBarActor::ComputeScalarBarLength()
{
  this->P->ScalarBarBox.Size[1] =
    this->Orientation == VTK_ORIENT_VERTICAL ?
Mathieu Westphal's avatar
Mathieu Westphal committed
1242 1243 1244
    this->P->Frame.Size[1] - this->P->TitleBox.Size[1] -
    this->VerticalTitleSeparation :
    this->P->Frame.Size[1];
1245

Mathieu Westphal's avatar
Mathieu Westphal committed
1246 1247
  // The scalar bar does not include the Nan Swatch, the Below Range Swatch and
  // the Above Range Swatch.
1248 1249
  this->P->ScalarBarBox.Size[1] = static_cast<int>(this->P->ScalarBarBox.Size[1] -
    (this->P->NanSwatchSize + this->P->SwatchPad));
Mathieu Westphal's avatar
Mathieu Westphal committed
1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265

  // Correct Swatch behevior while keeping compat with images from tests
  if (this->P->BelowRangeSwatchSize > 0)
    {
    this->P->ScalarBarBox.Size[1] -=
      this->P->BelowRangeSwatchSize + this->P->SwatchPad;
    }

  if (this->P->AboveRangeSwatchSize > 0)
    {
    this->P->ScalarBarBox.Size[1] -= this->P->AboveRangeSwatchSize;
    if (this->P->NanSwatchSize > 0)
      {
      this->P->ScalarBarBox.Size[1] -= this->P->SwatchPad;
      }
    }
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275
}

//-----------------------------------------------------------------------------
void vtkScalarBarActor::LayoutTicks()
{
  if (this->LookupTable->GetIndexedLookup())
    { // no tick marks in indexed lookup mode.
    this->NumberOfLabelsBuilt = 0;
    return;
    }
1276

1277
  // find the best size for the ticks
1278
  const double* range = this->LookupTable->GetRange();
1279
  char string[512];
Ken Martin's avatar
Ken Martin committed
1280
  double val;
Ken Martin's avatar
Ken Martin committed
1281
  int i;
1282

1283 1284 1285 1286 1287
  // TODO: this should be optimized, maybe by keeping a list of
  // allocated mappers, in order to avoid creation/destruction of
  // their underlying text properties (i.e. each time a mapper is
  // created, text properties are created and shallow-assigned a font size
  // which value might be "far" from the target font size).
1288
  this->P->TextActors.resize(this->NumberOfLabels);
1289

1290
  // Does this map have its scale set to log?
1291
  int isLogTable = this->LookupTable->UsingLogScale();
1292

1293
  for (i = 0; i < this->NumberOfLabels; i++)
Ken Martin's avatar
Ken Martin committed
1294
    {
1295
    this->P->TextActors[i].TakeReference(vtkTextActor::New());