DUDS
Distributed Update of Data from Something
BppPositionIndicator.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the DUDS project. It is subject to the BSD-style
3  * license terms in the LICENSE file found in the top-level directory of this
4  * distribution and at https://github.com/jjackowski/duds/blob/master/LICENSE.
5  * No part of DUDS, including this file, may be copied, modified, propagated,
6  * or distributed except according to the terms contained in the LICENSE file.
7  *
8  * Copyright (C) 2020 Jeff Jackowski
9  */
10 
12 #include <duds/general/Errors.hpp>
13 
14 namespace duds { namespace ui { namespace graphics {
15 
17  const ImageLocation &indicatorPos,
18  const ImageDimensions &indicatorDim,
19  std::uint16_t minMarkSize,
20  bool backgroundState
21 ) : ipos(indicatorPos), idim(indicatorDim), bstate(backgroundState)
22 {
23  // the indicator needs at least 3 pixels to move about
24  if (indicatorDim.empty() || ((indicatorDim.h < 3) && (indicatorDim.w < 3))) {
26  ImageErrorDimensions(indicatorDim)
27  );
28  }
29  // checks sizes; may throw
30  this->minMarkerSize(minMarkSize);
31 }
32 
34  const ImageDimensions &dim
35 ) {
36  if (dim.empty() || ((dim.h >= dim.w) && (minSize > (dim.h - 2))) ||
37  (!(dim.h >= dim.w) && (minSize > (dim.w - 2)))
38  ) {
41  );
42  }
43  idim = dim;
44 }
45 
46 void BppPositionIndicator::minMarkerSize(std::uint16_t size) {
47  if ((size < 1) ||
48  (vertical() && (size > (idim.h - 2))) ||
49  (!vertical() && (size > (idim.w - 2)))
50  ) {
53  );
54  }
55  minSize = size;
56 }
57 
58 void BppPositionIndicator::range(std::uint16_t r) {
59  if (r < 1) {
62  );
63  }
64  rng = r - 1;
65 }
66 
67 int BppPositionIndicator::position(int pos, int len) const {
68  // position is at the start of the range?
69  if (pos <= 0) {
70  return 0;
71  }
72  // position is at the end of the range?
73  if (pos >= rng) {
74  return len;
75  }
76  // position is somewhere in the middle of the range.
77  // Find position for shortened length to ensure start and end positions are
78  // distinctly different from in-between positions, even after rounding
79  // errors and such.
80  return pos * (len - 2) / rng + 1;
81 }
82 
83 void BppPositionIndicator::render(BppImage *dest, int start, int end) {
84  // top or left
85  ImageLocation tl = ipos;
86  ImageDimensions isize;
87  // length to fill
88  int len;
89  if (vertical()) {
90  len = idim.h;
91  isize.w = idim.w;
92  } else {
93  // make location seem to be vertical
94  tl.swapAxes();
95  len = idim.w;
96  isize.w = idim.h;
97  }
98  int sp, ep;
99  // indicate a range?
100  if (end > start) {
101  // start position
102  sp = position(start, len);
103  // end position
104  ep = position(end, len);
105  // length too short?
106  if ((ep - sp) < minSize) {
107  if (sp == 0) {
108  // start the minimum length from the begining
109  ep = minSize;
110  } else if (ep == len) {
111  // start the minimum length from the end
112  sp = ep - minSize;
113  } else {
114  // find the mid-point of the range and use the signle position
115  // code below
116  start = end = (start + end) / 2;
117  ep = 0;
118  }
119  }
120  // set position & dimension of indicator
121  if (ep) {
122  tl.y += sp;
123  isize.h = ep - sp;
124  }
125  } else {
126  ep = 0;
127  }
128  // indicate a single position, or a range too small for minimum length?
129  if (end <= start) {
130  // remove minimum length from the indicator's movement range
131  len -= minSize;
132  // find top or left position of indicator
133  sp = position(start, len);
134  tl.y += sp;
135  // always use minimum size
136  isize.h = minSize;
137  }
138  // code above works on vertical data
139  if (horizontal()) {
140  // switch to horizontal
141  tl.swapAxes();
142  isize.swapAxes();
143  // blank indicator; probably more efficent that blanking two sections
144  // because of the image data arrangement
145  dest->drawBox(ipos, idim, bstate);
146  } else if (sp) {
147  // blank indicator
148  // top first
149  dest->drawBox(ipos, ImageDimensions(idim.w, sp - 1), bstate);
150  }
151  // render indicator
152  dest->drawBox(tl, isize, !bstate);
153  if ((ep != len) && vertical()) {
154  // blank indicator
155  // bottom next
156  dest->drawBox(
157  ImageLocation(tl.x, tl.y + isize.h + 1),
158  ImageDimensions(idim.w, idim.h - isize.h - sp - 1),
159  bstate
160  );
161  }
162 
163 }
164 
165 } } }
ImageDimensions idim
The size of the indicator.
ImageLocation ipos
The location to render the indicator.
boost::error_info< struct Info_ImageDimensions, ImageDimensions > ImageErrorDimensions
Image dimensions relevant to the error.
Definition: BppImage.hpp:293
Stores a location within an image.
Definition: BppImage.hpp:33
std::int16_t y
Vertical coordinate.
Definition: BppImage.hpp:41
std::int16_t x
Horizontal coordinate.
Definition: BppImage.hpp:37
constexpr bool empty() const
True if the dimensions indicate zero area.
Definition: BppImage.hpp:169
Stores the dimensions of an image.
Definition: BppImage.hpp:125
boost::error_info< struct Info_IndicatorMinimumSize, std::uint16_t > PositionMarkMinimumSize
Error attribute with the length of the position mark in pixels.
const ImageDimensions & dimensions() const
Returns the dimensions (size) of the rendered indicator.
BppPositionIndicator()=default
Makes a new indicator with its position, dimensions, and range left uninitialized.
An attempt was made to set the range to zero.
void drawBox(ImageLocation ul, ImageDimensions id, Operation op=OpSet)
Draws a box into this image.
Definition: BppImage.cpp:485
boost::error_info< struct Info_IndicatorRange, std::uint16_t > IndicatorRange
Error attribute with the range of positions for a position indicator.
bool horizontal() const
True when the indicator&#39;s marker will move horizontally.
void swapAxes()
Swaps the dimensions&#39;s axes.
Definition: BppImage.hpp:202
bool bstate
The pixel state used for the background, the area not covered by the indicator mark/slider thingy...
void render(BppImage *dest, int start, int end=0)
Renders the indicator with the marker showing the given position.
An attempt was made to set the dimensions to a size that is too small to fit the position mark with e...
An attempt was made to set a minimum marker size that is less than one, or that is too large to fit w...
std::uint16_t minMarkerSize() const
Returns the minimum size of the position marker in pixels.
std::uint16_t range() const
Returns the range of positions that will be represented by the indicator.
bool vertical() const
True when the indicator&#39;s marker will move vertically.
General graphics related code.
Definition: HD44780.hpp:15
std::uint16_t minSize
The minimum length of the position marker.
std::uint16_t rng
The range of position values that may be used.
General errors.
#define DUDS_THROW_EXCEPTION(x)
Works like BOOST_THROW_EXCEPTION, but includes a stack trace if DUDS_ERRORS_VERBOSE is defined...
Definition: Errors.hpp:48
const ImageLocation & position() const
Returns the upper left position where the indictor will be drawn.
An image that uses a single bit to represent the state of each pixel; a black or white picture...
Definition: BppImage.hpp:321
void swapAxes()
Swaps the location&#39;s axes.
Definition: BppImage.hpp:97