/indra/newview/llcolorswatch.cpp
C++ | 373 lines | 269 code | 48 blank | 56 comment | 35 complexity | 4a21a84c3d3378a4be42ca2c8293559a MD5 | raw file
Possible License(s): LGPL-2.1
1/**
2 * @file llcolorswatch.cpp
3 * @brief LLColorSwatch class implementation
4 *
5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
6 * Second Life Viewer Source Code
7 * Copyright (C) 2010, Linden Research, Inc.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation;
12 * version 2.1 of the License only.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
24 * $/LicenseInfo$
25 */
26
27#include "llviewerprecompiledheaders.h"
28
29// File include
30#include "llcolorswatch.h"
31
32// Linden library includes
33#include "v4color.h"
34#include "llwindow.h" // setCursor()
35
36// Project includes
37#include "llui.h"
38#include "llrender.h"
39#include "lluiconstants.h"
40#include "llviewercontrol.h"
41#include "llbutton.h"
42#include "lltextbox.h"
43#include "llfloatercolorpicker.h"
44#include "llviewborder.h"
45#include "llviewertexturelist.h"
46#include "llfocusmgr.h"
47
48static LLDefaultChildRegistry::Register<LLColorSwatchCtrl> r("color_swatch");
49
50LLColorSwatchCtrl::Params::Params()
51: color("color", LLColor4::white),
52 can_apply_immediately("can_apply_immediately", false),
53 alpha_background_image("alpha_background_image"),
54 border_color("border_color"),
55 label_width("label_width", -1),
56 label_height("label_height", -1),
57 caption_text("caption_text"),
58 border("border")
59{
60}
61
62LLColorSwatchCtrl::LLColorSwatchCtrl(const Params& p)
63: LLUICtrl(p),
64 mValid( TRUE ),
65 mColor(p.color()),
66 mCanApplyImmediately(p.can_apply_immediately),
67 mAlphaGradientImage(p.alpha_background_image),
68 mOnCancelCallback(p.cancel_callback()),
69 mOnSelectCallback(p.select_callback()),
70 mBorderColor(p.border_color()),
71 mLabelWidth(p.label_width),
72 mLabelHeight(p.label_height)
73{
74 LLTextBox::Params tp = p.caption_text;
75 // use custom label height if it is provided
76 mLabelHeight = mLabelHeight != -1 ? mLabelHeight : BTN_HEIGHT_SMALL;
77 // label_width is specified, not -1
78 if(mLabelWidth!= -1)
79 {
80 tp.rect(LLRect( 0, mLabelHeight, mLabelWidth, 0 ));
81 }
82 else
83 {
84 tp.rect(LLRect( 0, mLabelHeight, getRect().getWidth(), 0 ));
85 }
86
87 tp.initial_value(p.label());
88 mCaption = LLUICtrlFactory::create<LLTextBox>(tp);
89 addChild( mCaption );
90
91 LLRect border_rect = getLocalRect();
92 border_rect.mTop -= 1;
93 border_rect.mRight -=1;
94 border_rect.mBottom += mLabelHeight;
95
96 LLViewBorder::Params params = p.border;
97 params.rect(border_rect);
98 mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
99 addChild(mBorder);
100}
101
102LLColorSwatchCtrl::~LLColorSwatchCtrl ()
103{
104 // parent dialog is destroyed so we are too and we need to cancel selection
105 LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
106 if (pickerp)
107 {
108 pickerp->cancelSelection();
109 pickerp->closeFloater();
110 }
111}
112
113BOOL LLColorSwatchCtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
114{
115 return handleMouseDown(x, y, mask);
116}
117
118BOOL LLColorSwatchCtrl::handleHover(S32 x, S32 y, MASK mask)
119{
120 getWindow()->setCursor(UI_CURSOR_HAND);
121 return TRUE;
122}
123
124BOOL LLColorSwatchCtrl::handleUnicodeCharHere(llwchar uni_char)
125{
126 if( ' ' == uni_char )
127 {
128 showPicker(TRUE);
129 }
130 return LLUICtrl::handleUnicodeCharHere(uni_char);
131}
132
133// forces color of this swatch and any associated floater to the input value, if currently invalid
134void LLColorSwatchCtrl::setOriginal(const LLColor4& color)
135{
136 mColor = color;
137 LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
138 if (pickerp)
139 {
140 pickerp->setOrigRgb(mColor.mV[VRED], mColor.mV[VGREEN], mColor.mV[VBLUE]);
141 }
142}
143
144void LLColorSwatchCtrl::set(const LLColor4& color, BOOL update_picker, BOOL from_event)
145{
146 mColor = color;
147 LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
148 if (pickerp && update_picker)
149 {
150 pickerp->setCurRgb(mColor.mV[VRED], mColor.mV[VGREEN], mColor.mV[VBLUE]);
151 }
152 if (!from_event)
153 {
154 setControlValue(mColor.getValue());
155 }
156}
157
158void LLColorSwatchCtrl::setLabel(const std::string& label)
159{
160 mCaption->setText(label);
161}
162
163BOOL LLColorSwatchCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
164{
165 // Route future Mouse messages here preemptively. (Release on mouse up.)
166 // No handler is needed for capture lost since this object has no state that depends on it.
167 gFocusMgr.setMouseCapture( this );
168
169 return TRUE;
170}
171
172
173BOOL LLColorSwatchCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
174{
175 // We only handle the click if the click both started and ended within us
176 if( hasMouseCapture() )
177 {
178 // Release the mouse
179 gFocusMgr.setMouseCapture( NULL );
180
181 // If mouseup in the widget, it's been clicked
182 if ( pointInView(x, y) )
183 {
184 llassert(getEnabled());
185 llassert(getVisible());
186
187 // Focus the widget now in order to return the focus
188 // after the color picker is closed.
189 setFocus(TRUE);
190
191 showPicker(FALSE);
192 }
193 }
194
195 return TRUE;
196}
197
198// assumes GL state is set for 2D
199void LLColorSwatchCtrl::draw()
200{
201 // If we're in a focused floater, don't apply the floater's alpha to the color swatch (STORM-676).
202 F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
203
204 mBorder->setKeyboardFocusHighlight(hasFocus());
205 // Draw border
206 LLRect border( 0, getRect().getHeight(), getRect().getWidth(), mLabelHeight );
207 gl_rect_2d( border, mBorderColor.get(), FALSE );
208
209 LLRect interior = border;
210 interior.stretch( -1 );
211
212 // Check state
213 if ( mValid )
214 {
215 if (!mColor.isOpaque())
216 {
217 // Draw checker board.
218 gl_rect_2d_checkerboard(interior, alpha);
219 }
220
221 // Draw the color swatch
222 gl_rect_2d(interior, mColor % alpha, TRUE);
223
224 if (!mColor.isOpaque())
225 {
226 // Draw semi-transparent center area in filled with mColor.
227 LLColor4 opaque_color = mColor;
228 opaque_color.mV[VALPHA] = alpha;
229 gGL.color4fv(opaque_color.mV);
230 if (mAlphaGradientImage.notNull())
231 {
232 gGL.pushMatrix();
233 {
234 mAlphaGradientImage->draw(interior, mColor % alpha);
235 }
236 gGL.popMatrix();
237 }
238 }
239 }
240 else
241 {
242 if (!mFallbackImageName.empty())
243 {
244 LLPointer<LLViewerFetchedTexture> fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, TRUE,
245 LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
246 if( fallback_image->getComponents() == 4 )
247 {
248 gl_rect_2d_checkerboard( interior );
249 }
250 gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), fallback_image, LLColor4::white % alpha);
251 fallback_image->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
252 }
253 else
254 {
255 // Draw grey and an X
256 gl_rect_2d(interior, LLColor4::grey % alpha, TRUE);
257
258 gl_draw_x(interior, LLColor4::black % alpha);
259 }
260 }
261
262 LLUICtrl::draw();
263}
264
265void LLColorSwatchCtrl::setEnabled( BOOL enabled )
266{
267 mCaption->setEnabled( enabled );
268 LLView::setEnabled( enabled );
269
270 if (!enabled)
271 {
272 LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
273 if (pickerp)
274 {
275 pickerp->cancelSelection();
276 pickerp->closeFloater();
277 }
278 }
279}
280
281
282void LLColorSwatchCtrl::setValue(const LLSD& value)
283{
284 set(LLColor4(value), TRUE, TRUE);
285}
286
287//////////////////////////////////////////////////////////////////////////////
288// called (infrequently) when the color changes so the subject of the swatch can be updated.
289void LLColorSwatchCtrl::onColorChanged ( void* data, EColorPickOp pick_op )
290{
291 LLColorSwatchCtrl* subject = ( LLColorSwatchCtrl* )data;
292 if ( subject )
293 {
294 LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)subject->mPickerHandle.get();
295 if (pickerp)
296 {
297 // move color across from selector to internal widget storage
298 LLColor4 updatedColor ( pickerp->getCurR (),
299 pickerp->getCurG (),
300 pickerp->getCurB (),
301 subject->mColor.mV[VALPHA] ); // keep current alpha
302 subject->mColor = updatedColor;
303 subject->setControlValue(updatedColor.getValue());
304
305 if (pick_op == COLOR_CANCEL && subject->mOnCancelCallback)
306 {
307 subject->mOnCancelCallback( subject, LLSD());
308 }
309 else if (pick_op == COLOR_SELECT && subject->mOnSelectCallback)
310 {
311 subject->mOnSelectCallback( subject, LLSD() );
312 }
313 else
314 {
315 // just commit change
316 subject->onCommit ();
317 }
318 }
319 }
320}
321
322// This is called when the main floatercustomize panel is closed.
323// Since this class has pointers up to its parents, we need to cleanup
324// this class first in order to avoid a crash.
325void LLColorSwatchCtrl::closeFloaterColorPicker()
326{
327 LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
328 if (pickerp)
329 {
330 pickerp->setSwatch(NULL);
331 pickerp->closeFloater();
332 }
333
334 mPickerHandle.markDead();
335}
336
337void LLColorSwatchCtrl::setValid(BOOL valid )
338{
339 mValid = valid;
340
341 LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
342 if (pickerp)
343 {
344 pickerp->setActive(valid);
345 }
346}
347
348void LLColorSwatchCtrl::showPicker(BOOL take_focus)
349{
350 LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
351 if (!pickerp)
352 {
353 pickerp = new LLFloaterColorPicker(this, mCanApplyImmediately);
354 LLFloater* parent = gFloaterView->getParentFloater(this);
355 if (parent)
356 {
357 parent->addDependentFloater(pickerp);
358 }
359 mPickerHandle = pickerp->getHandle();
360 }
361
362 // initialize picker with current color
363 pickerp->initUI ( mColor.mV [ VRED ], mColor.mV [ VGREEN ], mColor.mV [ VBLUE ] );
364
365 // display it
366 pickerp->showUI ();
367
368 if (take_focus)
369 {
370 pickerp->setFocus(TRUE);
371 }
372}
373