Delegation
Some possible Perl code for ColorSlider:
1 use AWT;
2 use AWT::Event;
3 use artofillusion qw (RGBColor);
4
5 use strict;
6
7 package ColorSlider;
8 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
9
10 @ISA = qw (Component);
11 @EXPORT = qw (); #defer this
12
13 $ColorSlider::HORIZONTAL = 1;
14 $ColorSlider::VERTICAL = 0;
15
16 sub new {
17
18 my $self = {
19 preferredMajor => 200,
20 preferredMinor => 18,
21
22 bubblePos => 50,
23 tempBubblePos => 50,
24
25 dragging => 0,
26
27 orientation => 0,
28 mode => $RGBColor::HSV_MODE,
29
30 baseImpl => new Canvas ()
31 };
32
33 my ($minimum, $maximum, $value, $orientation, $c1, $c2) = @_;
34
35 $self->{minimum} = $minimum;
36 $self->{maximum} = $maximum;
37 $self->{value} = $value;
38 $self->{orientation} = $orientation;
39 $self->{startColor} = new RGBColor ($c1);
40 $self->{endColor} = new RGBColor ($c2);
41
42 my $canvas = $self->baseImpl;
43 $canvas->setSize (200, 18);
44 $canvas->addMouseListener ($self);
45 $canvas->addMouseMotionListener ($self);
46 $canvas->setOnPaint (\&paint);
47 $canvas->setSubImpl ($self);
48
49 #So that routines that deal with components know where
50 #to go for native widget stuff
51 $self->setBaseImpl ($canvas);
52 $self->setOnSetSize (sub {$_[0]->_drawImage ()});
53 }
54
55
56 sub getPreferredSize {
57 my ($w, $h) = (200, 18);
58 $_[0]->getOrientation ? ($w, $h) : ($h, $w);
59 }
60
61
62 sub setColors {
63 my ($self, $c1, $c2) = @_;
64 $self->{startColor}->copy ($c1);
65 $self->{endColor}->copy ($c2);
66 $self->_drawImage ();
67 }
68
69 sub setMode {
70 my ($self, $mode) = @_;
71 $self->{mode} = $mode;
72 $self->_drawImage ();
73 }
74
75 sub _drawImage {
76 my $self = shift;
77 my ($w, $h) = getSize ();
78 my $startColor = $self->{startColor};
79 my $endColor = $self->{endColor};
80 my $mode = $self->{mode};
81 my $pixels = new PixelArray ($w, $h);
82
83 if ($self->{orientation}) {
84 $pixels->map (sub {
85 my ($x, $y, $p) = @_; #or they could be auto-assigned?
86 my $c = RGBColor::interp ($startColor, $endColor,
87 $mode, $x / $w)->getARGB | 0xff000000;
88 });
89 } else {
90 $pixels->map (sub {
91 my ($x, $y, $p) = @_;
92 my $c = RGBColor::interp ($startColor, $endColor,
93 $mode, $y / $h)->getARGB | 0xff000000;
94 });
95 }
96
97 $self->{image} = new Image (@pixels);
98 }
99
100
101 sub _drawImageFast {
102 my $self = shift;
103 my ($w, $h) = getSize ();
104 my $startColor = $self->{startColor};
105 my $endColor = $self->{endColor};
106 my $mode = $self->{mode};
107 my $pixels = new PixelArray ($w * $h);
108
109 if ($self->{orientation}) {
110 for (my $x = 0; $x < $w; $x++) {
111 my $c = RGBColor::interp ($startColor, $endColor,
112 $mode, $x / $w)->getARGB | 0xff000000;
113 $pixels->[$x + $_ * $w] = $c for (1..$h);
114 }
115 } else {
116 my $i = 0;
117 for (my $y = 0; $y < $h; $y++) {
118 my $c = RGBColor::interp ($startColor, $endColor,
119 $mode, $y / $h)->getARGB | 0xff000000;
120 $pixels->[$i++] = $c for (1..$w);
121 }
122 }
123
124 $self->{image} = new Image (@pixels);
125 }
126
127 sub _dragging {
128 $_[0]->{dragging};
129 }
130
131 sub mouseDragged {
132 my ($self, $event) = @_;
133 return if (!$self->_dragging);
134
135 my ($minor, $major) = ColorSlider::_getAxes ($event);
136
137 my ($w, $h) = $self->getSize ();
138 my $minorMax = $self->{orientation} ? $h : $w;
139 if ($minor > 0 && $minor < $minorMax) {
140 if ($major < 0) {
141 $self->setTempBubblePos (0);
142 } elsif ($major > 200) {
143 $self->setTempBubblePos (200);
144 } else {
145 $self->setTempBubblePos ($major);
146 }
147 $self->repaint;
148 }
149 }
150 sub setTempBubblePos {
151 $_[0]->{tempBubblePos} = $_[1];
152 }
153
154 sub mouseReleased {
155 my ($self, $event) = @_;
156
157 $self->{bubblePos} = $self->{tempBubblePos};
158
159 $self->{dragging} = 0;
160 $self->repaint;
161 $self->fireAdjustmentPerformed ();
162 }
163
164 sub _getAxes {
165 my $event = shift;
166 $_[0]->{orientation} ? ($event->{w}, $event->{h})
167 : ($event->{h}, $event->{w});
168 }
169
170 sub mousePressed {
171 my ($self, $event) = @_;
172
173 my ($minor, $major) = _getAxes ();
174 $self->{tempBubblePos} = $major;
175 $self->{dragging} = 1;
176 $self->repaint;
177 }
178
179 sub paint {
180
181 my ($self, $gc) = @_;
182
183 my ($width, $height) = $self->getSize ();
184
185 $self->drawImage () unless $self->{image};
186
187 my ($bubblePos, $tempBubblePos) =
188 ($self->{bubblePos}, $self->{tempBubblePos});
189
190 if ($self->{orientation}) {
191 my $h = $self->{preferredMinor};
192 my $w = $width;
193 my $top = ($height - $h) / 2;
194 $gc->drawImage ($self->{image}, 0, 6 + $top);
195
196 #outline
197 $gc->drawRect (0, 6 + $top, 200, 6);
198
199 #top of position marker
200 $gc->fillRect ($bubblePos, $top, 2, 6);
201
202 #bottom of position marker
203 $gc->fillRect ($bubblePos, 12 + $top, 2, $h - 12);
204
205 #top of temp position marker
206 $gc->fillRect ($tempBubblePos, $top, 2, 6);
207
208 #bottom of temp position marker
209 $gc->fillRect ($tempBubblePos, 12 + $top, 2, $h - 12);
210
211 } else {
212 #literate programming lets me ignore this case for now
213 }
214 }
215
216 sub getValue {
217 my $self = shift;
218 my $value = $self->{bubblePos} / 200;
219 $self->{value} = $value;
220 $value * $self->{maximum} + $self->{minimum};
221 }
222
223
224 sub setValue {
225 my ($self, $value) = @_;
226 $value = ($value - $self->{minimum}) / $self->{maximum};
227 $self->{bubblePos} = $value * 200;
228 $self->{tempBubblePos} = $self->{bubblePos};
229 $self->{value} = $value;
230 $self->repaint;
231 }