summaryrefslogtreecommitdiff
path: root/indra/newview/llfloatercolorpicker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llfloatercolorpicker.cpp')
-rw-r--r--indra/newview/llfloatercolorpicker.cpp1259
1 files changed, 1259 insertions, 0 deletions
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
new file mode 100644
index 0000000000..181a66c2ef
--- /dev/null
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -0,0 +1,1259 @@
+/**
+ * @file llfloatercolorpicker.cpp
+ * @brief Generic system color picker
+ *
+ * Copyright (c) 2004-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include <sstream>
+#include <iomanip>
+
+#include "llfloatercolorpicker.h"
+
+#include "llfontgl.h"
+#include "llsys.h"
+#include "llgl.h"
+#include "v3dmath.h"
+#include "lldir.h"
+#include "llui.h"
+#include "lllineeditor.h"
+#include "v4coloru.h"
+#include "llbutton.h"
+#include "llviewercontrol.h"
+#include "viewer.h"
+#include "llvieweruictrlfactory.h"
+#include "llviewerwindow.h"
+#include "llgl.h"
+#include "llmemory.h"
+#include "llimage.h"
+#include "llmousehandler.h"
+#include "llimagegl.h"
+#include "llglheaders.h"
+#include "llcheckboxctrl.h"
+#include "llworld.h"
+#include "lltextbox.h"
+#include "lluiconstants.h"
+#include "llfocusmgr.h"
+#include "lltoolmgr.h"
+#include "lltoolpipette.h"
+#include "lldraghandle.h"
+
+const F32 CONTEXT_CONE_IN_ALPHA = 0.0f;
+const F32 CONTEXT_CONE_OUT_ALPHA = 0.35f;
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Class LLFloaterColorPicker
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+// default ctor
+LLFloaterColorPicker::
+LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show_apply_immediate )
+ : LLFloater ("Color Picker Floater"),
+ mComponents ( 3 ),
+ mMouseDownInLumRegion ( FALSE ),
+ mMouseDownInHueRegion ( FALSE ),
+ mMouseDownInSwatch ( FALSE ),
+ mRGBViewerImageLeft ( 140 ),
+ mRGBViewerImageTop ( 356 ),
+ mRGBViewerImageWidth ( 256 ),
+ mRGBViewerImageHeight ( 256 ),
+ mLumRegionLeft ( mRGBViewerImageLeft + mRGBViewerImageWidth + 16 ),
+ mLumRegionTop ( mRGBViewerImageTop ),
+ mLumRegionWidth ( 16 ),
+ mLumRegionHeight ( mRGBViewerImageHeight ),
+ mLumMarkerSize ( 6 ),
+ mSwatchRegionLeft ( 12 ),
+ mSwatchRegionTop ( 160 + 16 - 4 ), // get help text baseline to line up with bottom of RGB viewer
+ mSwatchRegionWidth ( 110 ),
+ mSwatchRegionHeight ( 60 ),
+ mSwatchView ( NULL ),
+ numPaletteColumns ( 16 ),
+ numPaletteRows ( 2 ),
+ highlightEntry ( -1 ),
+ mPaletteRegionLeft ( mSwatchRegionLeft - 1 ),
+ mPaletteRegionTop ( 100 - 8 ),
+ mPaletteRegionWidth ( mLumRegionLeft + mLumRegionWidth - mSwatchRegionLeft + 2 ),
+ mPaletteRegionHeight ( 40 ),
+ mSwatch ( swatch ),
+ mActive ( TRUE ),
+ mCanApplyImmediately ( show_apply_immediate ),
+ mContextConeOpacity ( 0.f )
+{
+ // create user interface for this picker
+ createUI ();
+
+ if (!mCanApplyImmediately)
+ {
+ mApplyImmediateCheck->setEnabled(FALSE);
+ mApplyImmediateCheck->set(FALSE);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// dtor
+LLFloaterColorPicker::
+~LLFloaterColorPicker()
+{
+ // destroy the UI we created
+ destroyUI ();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void
+LLFloaterColorPicker::
+createUI ()
+{
+ // build the majority of the gui using the factory builder
+ gUICtrlFactory->buildFloater ( this, "floater_color_picker.xml" );
+ setVisible ( FALSE );
+
+ // create RGB type area (not really RGB but it's got R,G & B in it.,..
+
+ LLPointer<LLImageRaw> raw = new LLImageRaw ( mRGBViewerImageWidth, mRGBViewerImageHeight, mComponents );
+ U8* bits = raw->getData();
+ S32 linesize = mRGBViewerImageWidth * mComponents;
+ for ( S32 y = 0; y < mRGBViewerImageHeight; ++y )
+ {
+ for ( S32 x = 0; x < linesize; x += mComponents )
+ {
+ F32 rVal, gVal, bVal;
+
+ hslToRgb ( (F32)x / (F32) ( linesize - 1 ),
+ (F32)y / (F32) ( mRGBViewerImageHeight - 1 ),
+ 0.5f,
+ rVal,
+ gVal,
+ bVal );
+
+ * ( bits + x + y * linesize + 0 ) = ( U8 )( rVal * 255.0f );
+ * ( bits + x + y * linesize + 1 ) = ( U8 )( gVal * 255.0f );
+ * ( bits + x + y * linesize + 2 ) = ( U8 )( bVal * 255.0f );
+ }
+ }
+ mRGBImage = new LLImageGL ( (LLImageRaw*)raw, FALSE );
+ mRGBImage->bind();
+ mRGBImage->setClamp(TRUE, TRUE);
+
+ // create palette
+ for ( S32 each = 0; each < numPaletteColumns * numPaletteRows; ++each )
+ {
+ std::ostringstream codec;
+ codec << "ColorPaletteEntry" << std::setfill ( '0' ) << std::setw ( 2 ) << each + 1;
+
+ // argh!
+ const std::string s ( codec.str () );
+ mPalette.push_back ( new LLColor4 ( gSavedSettings.getColor4 ( s ) ) );
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void
+LLFloaterColorPicker::
+showUI ()
+{
+ setVisible ( TRUE );
+ setFocus ( TRUE );
+ open();
+
+ // HACK: if system color picker is required - close the SL one we made and use default system dialog
+ if ( gSavedSettings.getBOOL ( "UseDefaultColorPicker" ) )
+ {
+ LLColorSwatchCtrl* swatch = getSwatch ();
+
+ setVisible ( FALSE );
+
+ // code that will get switched in for default system color picker
+ if ( swatch )
+ {
+ LLColor4 curCol = swatch->get ();
+ send_agent_pause();
+ gViewerWindow->getWindow ()->dialog_color_picker ( &curCol [ 0 ], &curCol [ 1 ], &curCol [ 2 ] );
+ send_agent_resume();
+
+ setOrigRgb ( curCol [ 0 ], curCol [ 1 ], curCol [ 2 ] );
+ setCurRgb( curCol [ 0 ], curCol [ 1 ], curCol [ 2 ] );
+
+ LLColorSwatchCtrl::onColorChanged ( swatch, LLColorSwatchCtrl::COLOR_CHANGE );
+ }
+
+ close();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// called after the dialog is rendered
+BOOL
+LLFloaterColorPicker::
+postBuild()
+{
+ mCancelBtn = LLViewerUICtrlFactory::getButtonByName( this, "cancel_btn" );
+ mCancelBtn->setClickedCallback ( onClickCancel );
+ mCancelBtn->setCallbackUserData ( this );
+
+ mSelectBtn = LLViewerUICtrlFactory::getButtonByName( this, "select_btn");
+ mSelectBtn->setClickedCallback ( onClickSelect );
+ mSelectBtn->setCallbackUserData ( this );
+ mSelectBtn->setFocus ( TRUE );
+
+ mPipetteBtn = LLViewerUICtrlFactory::getButtonByName ( this, "color_pipette" );
+
+ mPipetteBtn->setImages("eye_button_inactive.tga", "eye_button_active.tga");
+
+ mPipetteBtn->setClickedCallback( onClickPipette );
+ mPipetteBtn->setCallbackUserData ( this );
+
+ mApplyImmediateCheck = LLViewerUICtrlFactory::getCheckBoxByName( this, "apply_immediate");
+ mApplyImmediateCheck->set(gSavedSettings.getBOOL("ApplyColorImmediately"));
+ mApplyImmediateCheck->setCommitCallback(onImmediateCheck);
+ mApplyImmediateCheck->setCallbackUserData(this);
+
+ childSetCommitCallback("rspin", onTextCommit, (void*)this );
+ childSetCommitCallback("gspin", onTextCommit, (void*)this );
+ childSetCommitCallback("bspin", onTextCommit, (void*)this );
+ childSetCommitCallback("hspin", onTextCommit, (void*)this );
+ childSetCommitCallback("sspin", onTextCommit, (void*)this );
+ childSetCommitCallback("lspin", onTextCommit, (void*)this );
+
+ return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void
+LLFloaterColorPicker::
+initUI ( F32 rValIn, F32 gValIn, F32 bValIn )
+{
+ // start catching lose-focus events from entry widgets
+ enableTextCallbacks ( TRUE );
+
+ // under some circumstances, we get rogue values that can be calmed by clamping...
+ rValIn = llclamp ( rValIn, 0.0f, 1.0f );
+ gValIn = llclamp ( gValIn, 0.0f, 1.0f );
+ bValIn = llclamp ( bValIn, 0.0f, 1.0f );
+
+ // store initial value in case cancel or revert is selected
+ setOrigRgb ( rValIn, gValIn, bValIn );
+
+ // starting point for current value to
+ setCurRgb ( rValIn, gValIn, bValIn );
+
+ // unpdate text entry fields
+ updateTextEntry ();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void
+LLFloaterColorPicker::
+destroyUI ()
+{
+ // shut down pipette tool if active
+ stopUsingPipette();
+
+ // delete palette we created
+ std::vector < LLColor4* >::iterator iter = mPalette.begin ();
+ while ( iter != mPalette.end () )
+ {
+ delete ( *iter );
+ ++iter;
+ }
+
+ if ( mSwatchView )
+ {
+ this->removeChild ( mSwatchView );
+ delete mSwatchView;
+ mSwatchView = NULL;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void
+LLFloaterColorPicker::
+rgbToHsl ( F32 rValIn, F32 gValIn, F32 bValIn, F32& hValOut, F32& sValOut, F32& lValOut )
+{
+ F32 var_R = ( rValIn );
+ F32 var_G = ( gValIn );
+ F32 var_B = ( bValIn );
+
+ F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) );
+ F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) );
+
+ F32 del_Max = var_Max - var_Min;
+
+ F32 L = ( var_Max + var_Min ) / 2.0f;
+ F32 H = 0.0f;
+ F32 S = 0.0f;
+
+ if ( del_Max == 0.0f )
+ {
+ H = 0.0f;
+ S = 0.0f;
+ }
+ else
+ {
+ if ( L < 0.5 )
+ S = del_Max / ( var_Max + var_Min );
+ else
+ S = del_Max / ( 2.0f - var_Max - var_Min );
+
+ F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+ F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+ F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+
+ if ( var_R >= var_Max )
+ H = del_B - del_G;
+ else
+ if ( var_G >= var_Max )
+ H = ( 1.0f / 3.0f ) + del_R - del_B;
+ else
+ if ( var_B >= var_Max )
+ H = ( 2.0f / 3.0f ) + del_G - del_R;
+
+ if ( H < 0.0f ) H += 1.0f;
+ if ( H > 1.0f ) H -= 1.0f;
+ }
+
+ // scale to meet calculation requirements
+ hValOut = H * 360.0f / 360.0f;
+ sValOut = S * 100.0f / 100.0f;
+ lValOut = L * 100.0f / 100.0f;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+F32
+LLFloaterColorPicker::
+hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
+{
+ if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
+ if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
+ if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
+ if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
+ if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
+ return ( val1In );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void
+LLFloaterColorPicker::
+hslToRgb ( F32 hValIn, F32 sValIn, F32 lValIn, F32& rValOut, F32& gValOut, F32& bValOut )
+{
+ if ( sValIn < 0.00001f )
+ {
+ rValOut = lValIn;
+ gValOut = lValIn;
+ bValOut = lValIn;
+ }
+ else
+ {
+ F32 interVal1;
+ F32 interVal2;
+
+ if ( lValIn < 0.5f )
+ interVal2 = lValIn * ( 1.0f + sValIn );
+ else
+ interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
+
+ interVal1 = 2.0f * lValIn - interVal2;
+
+ rValOut = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
+ gValOut = hueToRgb ( interVal1, interVal2, hValIn );
+ bValOut = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// mutator for original RGB value
+void
+LLFloaterColorPicker::
+setOrigRgb ( F32 origRIn, F32 origGIn, F32 origBIn )
+{
+ origR = origRIn;
+ origG = origGIn;
+ origB = origBIn;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// accessor for original RGB value
+void
+LLFloaterColorPicker::
+getOrigRgb ( F32& origROut, F32& origGOut, F32& origBOut )
+{
+ origROut = origR;
+ origGOut = origG;
+ origBOut = origB;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// mutator for current RGB value
+void
+LLFloaterColorPicker::
+setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn )
+{
+ // save current RGB
+ curR = curRIn;
+ curG = curGIn;
+ curB = curBIn;
+
+ // update corresponding HSL values and
+ rgbToHsl ( curR, curG, curB, curH, curS, curL );
+
+ // color changed so update text fields (fixes SL-16968)
+ // HACK: turn off the call back wilst we update the text or we recurse ourselves into oblivion
+ // CP: this was required when I first wrote the code but this may not be necessary anymore - leaving it there just in case
+ enableTextCallbacks( FALSE );
+ updateTextEntry();
+ enableTextCallbacks( TRUE );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// accessor for current RGB value
+void
+LLFloaterColorPicker::
+getCurRgb ( F32& curROut, F32& curGOut, F32& curBOut )
+{
+ curROut = curR;
+ curGOut = curG;
+ curBOut = curB;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// mutator for current HSL value
+void
+LLFloaterColorPicker::
+setCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn )
+{
+ // save current HSL
+ curH = curHIn;
+ curS = curSIn;
+ curL = curLIn;
+
+ // update corresponding RGB values and
+ hslToRgb ( curH, curS, curL, curR, curG, curB );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// accessor for current HSL value
+void
+LLFloaterColorPicker::
+getCurHsl ( F32& curHOut, F32& curSOut, F32& curLOut )
+{
+ curHOut = curH;
+ curSOut = curS;
+ curLOut = curL;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// called when 'cancel' clicked
+void
+LLFloaterColorPicker::
+onClickCancel ( void* data )
+{
+ if (data)
+ {
+ LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
+
+ if ( self )
+ {
+ self->cancelSelection ();
+ self->close();
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// called when 'select' clicked
+void
+LLFloaterColorPicker::
+onClickSelect ( void* data )
+{
+ if (data)
+ {
+ LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
+
+ if ( self )
+ {
+ // apply to selection
+ LLColorSwatchCtrl::onColorChanged ( self->getSwatch (), LLColorSwatchCtrl::COLOR_SELECT );
+ self->close();
+ }
+ }
+}
+
+void LLFloaterColorPicker::onClickPipette( void* data )
+{
+ LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
+
+ if ( self && gToolMgr)
+ {
+ BOOL pipette_active = self->mPipetteBtn->getToggleState();
+ pipette_active = !pipette_active;
+ if (pipette_active)
+ {
+ gToolPipette->setSelectCallback(onColorSelect, self);
+ gToolMgr->setTransientTool(gToolPipette);
+ }
+ else
+ {
+ gToolMgr->clearTransientTool();
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// called when 'text is committed' - i,e. focus moves from a text field
+void
+LLFloaterColorPicker::
+onTextCommit ( LLUICtrl* ctrl, void* data )
+{
+ if ( data )
+ {
+ LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
+ if ( self )
+ {
+ self->onTextEntryChanged ( ctrl );
+ }
+ }
+}
+
+void LLFloaterColorPicker::onImmediateCheck( LLUICtrl* ctrl, void* data)
+{
+ LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
+ if (self)
+ {
+ gSavedSettings.setBOOL("ApplyColorImmediately", self->mApplyImmediateCheck->get());
+
+ if (self->mApplyImmediateCheck->get())
+ {
+ LLColorSwatchCtrl::onColorChanged ( self->getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
+ }
+ }
+}
+
+void LLFloaterColorPicker::onColorSelect( const LLTextureEntry& te, void *data )
+{
+ LLFloaterColorPicker* self = (LLFloaterColorPicker*)data;
+ if (self)
+ {
+ self->setCurRgb(te.getColor().mV[VRED], te.getColor().mV[VGREEN], te.getColor().mV[VBLUE]);
+ if (self->mApplyImmediateCheck->get())
+ {
+ LLColorSwatchCtrl::onColorChanged ( self->getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
+ }
+ }
+}
+
+void LLFloaterColorPicker::onMouseCaptureLost(LLMouseHandler *old_captor)
+{
+ LLFloaterColorPicker* self = (LLFloaterColorPicker*)old_captor;
+ self->setMouseDownInHueRegion(FALSE);
+ self->setMouseDownInLumRegion(FALSE);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void LLFloaterColorPicker::draw()
+{
+ LLRect swatch_rect;
+ mSwatch->localRectToOtherView(mSwatch->getLocalRect(), &swatch_rect, this);
+ // draw context cone connecting color picker with color swatch in parent floater
+ LLRect local_rect = getLocalRect();
+ if (gFocusMgr.childHasKeyboardFocus(this) && mSwatch->isInVisibleChain() && mContextConeOpacity > 0.001f)
+ {
+ LLGLSNoTexture no_texture;
+ LLGLEnable(GL_CULL_FACE);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
+ glVertex2i(swatch_rect.mLeft, swatch_rect.mTop);
+ glVertex2i(swatch_rect.mRight, swatch_rect.mTop);
+ glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
+ glVertex2i(local_rect.mRight, local_rect.mTop);
+ glVertex2i(local_rect.mLeft, local_rect.mTop);
+
+ glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
+ glVertex2i(local_rect.mLeft, local_rect.mTop);
+ glVertex2i(local_rect.mLeft, local_rect.mBottom);
+ glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
+ glVertex2i(swatch_rect.mLeft, swatch_rect.mBottom);
+ glVertex2i(swatch_rect.mLeft, swatch_rect.mTop);
+
+ glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
+ glVertex2i(local_rect.mRight, local_rect.mBottom);
+ glVertex2i(local_rect.mRight, local_rect.mTop);
+ glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
+ glVertex2i(swatch_rect.mRight, swatch_rect.mTop);
+ glVertex2i(swatch_rect.mRight, swatch_rect.mBottom);
+
+ glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
+ glVertex2i(local_rect.mLeft, local_rect.mBottom);
+ glVertex2i(local_rect.mRight, local_rect.mBottom);
+ glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
+ glVertex2i(swatch_rect.mRight, swatch_rect.mBottom);
+ glVertex2i(swatch_rect.mLeft, swatch_rect.mBottom);
+ }
+ glEnd();
+ }
+
+ if (gFocusMgr.childHasMouseCapture(mDragHandle))
+ {
+ mContextConeOpacity = lerp(mContextConeOpacity, 1.f, LLCriticalDamp::getInterpolant(0.1f));
+ }
+ else
+ {
+ mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(0.2f));
+ }
+
+ mPipetteBtn->setEnabled(gToolMgr != NULL);
+ mPipetteBtn->setToggleState(gToolMgr && gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolPipette);
+ mApplyImmediateCheck->setEnabled(mActive && mCanApplyImmediately);
+ mSelectBtn->setEnabled(mActive);
+
+ // base floater stuff
+ LLFloater::draw ();
+
+ // draw image for RGB area (not really RGB but you'll see what I mean...
+ gl_draw_image ( mRGBViewerImageLeft, mRGBViewerImageTop - mRGBViewerImageHeight, mRGBImage, LLColor4::white );
+
+ // update 'cursor' into RGB Section
+ S32 xPos = ( S32 ) ( ( F32 )mRGBViewerImageWidth * getCurH () ) - 8;
+ S32 yPos = ( S32 ) ( ( F32 )mRGBViewerImageHeight * getCurS () ) - 8;
+ gl_line_2d ( mRGBViewerImageLeft + xPos,
+ mRGBViewerImageTop - mRGBViewerImageHeight + yPos + 8,
+ mRGBViewerImageLeft + xPos + 16,
+ mRGBViewerImageTop - mRGBViewerImageHeight + yPos + 8,
+ LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ) );
+
+ gl_line_2d ( mRGBViewerImageLeft + xPos + 8,
+ mRGBViewerImageTop - mRGBViewerImageHeight + yPos,
+ mRGBViewerImageLeft + xPos + 8,
+ mRGBViewerImageTop - mRGBViewerImageHeight + yPos + 16,
+ LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ) );
+
+ // create rgb area outline
+ gl_rect_2d ( mRGBViewerImageLeft,
+ mRGBViewerImageTop - mRGBViewerImageHeight,
+ mRGBViewerImageLeft + mRGBViewerImageWidth,
+ mRGBViewerImageTop,
+ LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
+ FALSE );
+
+ // draw luminance slider
+ for ( S32 y = 0; y < mLumRegionHeight; ++y )
+ {
+ F32 rValSlider, gValSlider, bValSlider;
+ hslToRgb ( getCurH (), getCurS (), ( F32 )y / ( F32 )mLumRegionHeight, rValSlider, gValSlider, bValSlider );
+
+ gl_rect_2d( mLumRegionLeft,
+ mLumRegionTop - mLumRegionHeight + y,
+ mLumRegionLeft + mLumRegionWidth,
+ mLumRegionTop - mLumRegionHeight + y - 1,
+ LLColor4 ( rValSlider, gValSlider, bValSlider, 1.0f ) );
+ }
+
+
+ // draw luninance marker
+ S32 startX = mLumRegionLeft + mLumRegionWidth;
+ S32 startY = mLumRegionTop - mLumRegionHeight + ( S32 ) ( mLumRegionHeight * getCurL () );
+ gl_triangle_2d ( startX, startY,
+ startX + mLumMarkerSize, startY - mLumMarkerSize,
+ startX + mLumMarkerSize, startY + mLumMarkerSize,
+ LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ), TRUE );
+
+ // draw luminance slider outline
+ gl_rect_2d ( mLumRegionLeft,
+ mLumRegionTop - mLumRegionHeight,
+ mLumRegionLeft + mLumRegionWidth,
+ mLumRegionTop,
+ LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
+ FALSE );
+
+ // draw selected color swatch
+ gl_rect_2d ( mSwatchRegionLeft,
+ mSwatchRegionTop - mSwatchRegionHeight,
+ mSwatchRegionLeft + mSwatchRegionWidth,
+ mSwatchRegionTop,
+ LLColor4 ( getCurR (), getCurG (), getCurB (), 1.0f ),
+ TRUE );
+
+ // draw selected color swatch outline
+ gl_rect_2d ( mSwatchRegionLeft,
+ mSwatchRegionTop - mSwatchRegionHeight,
+ mSwatchRegionLeft + mSwatchRegionWidth,
+ mSwatchRegionTop,
+ LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
+ FALSE );
+
+ // color palette code is a little more involved so break it out into its' own method
+ drawPalette ();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// find a complimentary color to the one passed in that can be used to highlight
+LLColor4&
+LLFloaterColorPicker::
+getComplimentaryColor ( LLColor4& backgroundColor )
+{
+ // going to base calculation on luminance
+ F32 hVal, sVal, lVal;
+ rgbToHsl ( backgroundColor [ 0 ], backgroundColor [ 1 ], backgroundColor [ 2 ], hVal, sVal, lVal );
+
+ // fairly simple heuristic for now...!
+ if ( lVal < 0.5f )
+ {
+ return LLColor4::white;
+ }
+
+ return LLColor4::black;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// draw color palette
+void
+LLFloaterColorPicker::
+drawPalette ()
+{
+ S32 curEntry = 0;
+
+ for ( S32 y = 0; y < numPaletteRows; ++y )
+ {
+ for ( S32 x = 0; x < numPaletteColumns; ++x )
+ {
+ // calculate position
+ S32 x1 = mPaletteRegionLeft + ( mPaletteRegionWidth * x ) / numPaletteColumns;
+ S32 y1 = mPaletteRegionTop - ( mPaletteRegionHeight * y ) / numPaletteRows;
+ S32 x2 = ( mPaletteRegionLeft + ( mPaletteRegionWidth * ( x + 1 ) ) / numPaletteColumns );
+ S32 y2 = ( mPaletteRegionTop - ( mPaletteRegionHeight * ( y + 1 ) ) / numPaletteRows );
+
+ // draw palette entry color
+ if ( mPalette [ curEntry ] )
+ {
+ gl_rect_2d ( x1 + 2, y1 - 2, x2 - 2, y2 + 2, *mPalette [ curEntry++ ], TRUE );
+ gl_rect_2d ( x1 + 1, y1 - 1, x2 - 1, y2 + 1, LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ), FALSE );
+ }
+ }
+ }
+
+ // if there is something to highlight (mouse down in swatch & hovering over palette)
+ if ( highlightEntry >= 0 )
+ {
+ // extract row/column from palette index
+ S32 entryColumn = highlightEntry % numPaletteColumns;
+ S32 entryRow = highlightEntry / numPaletteColumns;
+
+ // calculate position of this entry
+ S32 x1 = mPaletteRegionLeft + ( mPaletteRegionWidth * entryColumn ) / numPaletteColumns;
+ S32 y1 = mPaletteRegionTop - ( mPaletteRegionHeight * entryRow ) / numPaletteRows;
+ S32 x2 = ( mPaletteRegionLeft + ( mPaletteRegionWidth * ( entryColumn + 1 ) ) / numPaletteColumns );
+ S32 y2 = ( mPaletteRegionTop - ( mPaletteRegionHeight * ( entryRow + 1 ) ) / numPaletteRows );
+
+ // center position of entry
+ S32 xCenter = x1 + ( x2 - x1 ) / 2;
+ S32 yCenter = y1 - ( y1 - y2 ) / 2;
+
+ // find a color that works well as a highlight color
+ LLColor4 hlColor ( getComplimentaryColor ( *mPalette [ highlightEntry ] ) );
+
+ // mark a cross for entry that is being hovered
+ gl_line_2d ( xCenter - 4, yCenter - 4, xCenter + 4, yCenter + 4, hlColor );
+ gl_line_2d ( xCenter + 4, yCenter - 4, xCenter - 4, yCenter + 4, hlColor );
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// update text entry values for RGB/HSL (can't be done in ::draw () since this overwrites input
+void
+LLFloaterColorPicker::
+updateTextEntry ()
+{
+ // set values in spinners
+ childSetValue("rspin", ( getCurR () * 255.0f ) );
+ childSetValue("gspin", ( getCurG () * 255.0f ) );
+ childSetValue("bspin", ( getCurB () * 255.0f ) );
+ childSetValue("hspin", ( getCurH () * 360.0f ) );
+ childSetValue("sspin", ( getCurS () * 100.0f ) );
+ childSetValue("lspin", ( getCurL () * 100.0f ) );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// turns on or off text entry commit call backs
+void
+LLFloaterColorPicker::
+enableTextCallbacks ( BOOL stateIn )
+{
+ if ( stateIn )
+ {
+ childSetCommitCallback("rspin", onTextCommit, (void*)this );
+ childSetCommitCallback("gspin", onTextCommit, (void*)this );
+ childSetCommitCallback("bspin", onTextCommit, (void*)this );
+ childSetCommitCallback("hspin", onTextCommit, (void*)this );
+ childSetCommitCallback("sspin", onTextCommit, (void*)this );
+ childSetCommitCallback("lspin", onTextCommit, (void*)this );
+ }
+ else
+ {
+ childSetCommitCallback("rspin", 0, (void*)this );
+ childSetCommitCallback("gspin", 0, (void*)this );
+ childSetCommitCallback("bspin", 0, (void*)this );
+ childSetCommitCallback("hspin", 0, (void*)this );
+ childSetCommitCallback("sspin", 0, (void*)this );
+ childSetCommitCallback("lspin", 0, (void*)this );
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void
+LLFloaterColorPicker::
+onTextEntryChanged ( LLUICtrl* ctrl )
+{
+ // value in RGB boxes changed
+ LLString name = ctrl->getName();
+ if ( ( name == "rspin" ) || ( name == "gspin" ) || ( name == "bspin" ) )
+ {
+ // get current RGB
+ F32 rVal, gVal, bVal;
+ getCurRgb ( rVal, gVal, bVal );
+
+ // update component value with new value from text
+ if ( name == "rspin" )
+ {
+ rVal = (F32)ctrl->getValue().asReal() / 255.0f;
+ }
+ else
+ if ( name == "gspin" )
+ {
+ gVal = (F32)ctrl->getValue().asReal() / 255.0f;
+ }
+ else
+ if ( name == "bspin" )
+ {
+ bVal = (F32)ctrl->getValue().asReal() / 255.0f;
+ }
+
+ // update current RGB (and implicitly HSL)
+ setCurRgb ( rVal, gVal, bVal );
+
+ // HACK: turn off the call back wilst we update the text or we recurse ourselves into oblivion
+ enableTextCallbacks ( FALSE );
+ updateTextEntry ();
+ enableTextCallbacks ( TRUE );
+ }
+ else
+ // value in HSL boxes changed
+ if ( ( name == "hspin" ) || ( name == "sspin" ) || ( name == "lspin" ) )
+ {
+ // get current HSL
+ F32 hVal, sVal, lVal;
+ getCurHsl ( hVal, sVal, lVal );
+
+ // update component value with new value from text
+ if ( name == "hspin" )
+ hVal = (F32)ctrl->getValue().asReal() / 360.0f;
+ else
+ if ( name == "sspin" )
+ sVal = (F32)ctrl->getValue().asReal() / 100.0f;
+ else
+ if ( name == "lspin" )
+ lVal = (F32)ctrl->getValue().asReal() / 100.0f;
+
+ // update current HSL (and implicitly RGB)
+ setCurHsl ( hVal, sVal, lVal );
+
+ // HACK: turn off the call back wilst we update the text or we recurse ourselves into oblivion
+ enableTextCallbacks ( FALSE );
+ updateTextEntry ();
+ enableTextCallbacks ( TRUE );
+ }
+
+ if (mApplyImmediateCheck->get())
+ {
+ LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLFloaterColorPicker::
+updateRgbHslFromPoint ( S32 xPosIn, S32 yPosIn )
+{
+ if ( xPosIn >= mRGBViewerImageLeft &&
+ xPosIn <= mRGBViewerImageLeft + mRGBViewerImageWidth &&
+ yPosIn <= mRGBViewerImageTop &&
+ yPosIn >= mRGBViewerImageTop - mRGBViewerImageHeight )
+ {
+ // update HSL (and therefore RGB) based on new H & S and current L
+ setCurHsl ( ( ( F32 )xPosIn - ( F32 )mRGBViewerImageLeft ) / ( F32 )mRGBViewerImageWidth,
+ ( ( F32 )yPosIn - ( ( F32 )mRGBViewerImageTop - ( F32 )mRGBViewerImageHeight ) ) / ( F32 )mRGBViewerImageHeight,
+ getCurL () );
+
+ // indicate a value changed
+ return TRUE;
+ }
+ else
+ if ( xPosIn >= mLumRegionLeft &&
+ xPosIn <= mLumRegionLeft + mLumRegionWidth &&
+ yPosIn <= mLumRegionTop &&
+ yPosIn >= mLumRegionTop - mLumRegionHeight )
+ {
+
+ // update HSL (and therefore RGB) based on current HS and new L
+ setCurHsl ( getCurH (),
+ getCurS (),
+ ( ( F32 )yPosIn - ( ( F32 )mRGBViewerImageTop - ( F32 )mRGBViewerImageHeight ) ) / ( F32 )mRGBViewerImageHeight );
+
+ // indicate a value changed
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLFloaterColorPicker::
+handleMouseDown ( S32 x, S32 y, MASK mask )
+{
+ // if this window is in the foreground
+ if ( mForeground )
+ {
+ // make it the frontmost
+ gFloaterView->bringToFront(this);
+
+ // rect containing RGB area
+ LLRect rgbAreaRect ( mRGBViewerImageLeft,
+ mRGBViewerImageTop,
+ mRGBViewerImageLeft + mRGBViewerImageWidth,
+ mRGBViewerImageTop - mRGBViewerImageHeight );
+
+ if ( rgbAreaRect.pointInRect ( x, y ) )
+ {
+ gViewerWindow->setMouseCapture(this, onMouseCaptureLost);
+ // mouse button down
+ setMouseDownInHueRegion ( TRUE );
+
+ // update all values based on initial click
+ updateRgbHslFromPoint ( x, y );
+
+ // required by base class
+ return TRUE;
+ }
+
+ // rect containing RGB area
+ LLRect lumAreaRect ( mLumRegionLeft,
+ mLumRegionTop,
+ mLumRegionLeft + mLumRegionWidth + mLumMarkerSize,
+ mLumRegionTop - mLumRegionHeight );
+
+ if ( lumAreaRect.pointInRect ( x, y ) )
+ {
+ gViewerWindow->setMouseCapture(this, onMouseCaptureLost);
+ // mouse button down
+ setMouseDownInLumRegion ( TRUE );
+
+ // required by base class
+ return TRUE;
+ }
+
+ // rect containing swatch area
+ LLRect swatchRect ( mSwatchRegionLeft,
+ mSwatchRegionTop,
+ mSwatchRegionLeft + mSwatchRegionWidth,
+ mSwatchRegionTop - mSwatchRegionHeight );
+
+ setMouseDownInSwatch( FALSE );
+ if ( swatchRect.pointInRect ( x, y ) )
+ {
+ setMouseDownInSwatch( TRUE );
+
+ // required - dont drag windows here.
+ return TRUE;
+ }
+
+ // rect containing palette area
+ LLRect paletteRect ( mPaletteRegionLeft,
+ mPaletteRegionTop,
+ mPaletteRegionLeft + mPaletteRegionWidth,
+ mPaletteRegionTop - mPaletteRegionHeight );
+
+ if ( paletteRect.pointInRect ( x, y ) )
+ {
+ // release keyboard focus so we can change text values
+ if (gFocusMgr.childHasKeyboardFocus(this))
+ {
+ mSelectBtn->setFocus(TRUE);
+ }
+
+ // calculate which palette index we selected
+ S32 c = ( ( x - mPaletteRegionLeft ) * numPaletteColumns ) / mPaletteRegionWidth;
+ S32 r = ( ( y - ( mPaletteRegionTop - mPaletteRegionHeight ) ) * numPaletteRows ) / mPaletteRegionHeight;
+
+ U32 index = ( numPaletteRows - r - 1 ) * numPaletteColumns + c;
+
+ if ( index <= mPalette.size () )
+ {
+ LLColor4 selected = *mPalette [ index ];
+
+ setCurRgb ( selected [ 0 ], selected [ 1 ], selected [ 2 ] );
+
+ if (mApplyImmediateCheck->get())
+ {
+ LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
+ }
+
+ // HACK: turn off the call back wilst we update the text or we recurse ourselves into oblivion
+ enableTextCallbacks ( FALSE );
+ updateTextEntry ();
+ enableTextCallbacks ( TRUE );
+ }
+
+ return TRUE;
+ }
+ }
+ // dispatch to base class for the rest of things
+ return LLFloater::handleMouseDown ( x, y, mask );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLFloaterColorPicker::
+handleHover ( S32 x, S32 y, MASK mask )
+{
+ // if we're the front most window
+ if ( isFrontmost () )
+ {
+ // mouse was pressed within region
+ if ( getMouseDownInHueRegion() || getMouseDownInLumRegion())
+ {
+ S32 clamped_x, clamped_y;
+ if (getMouseDownInHueRegion())
+ {
+ clamped_x = llclamp(x, mRGBViewerImageLeft, mRGBViewerImageLeft + mRGBViewerImageWidth);
+ clamped_y = llclamp(y, mRGBViewerImageTop - mRGBViewerImageHeight, mRGBViewerImageTop);
+ }
+ else
+ {
+ clamped_x = llclamp(x, mLumRegionLeft, mLumRegionLeft + mLumRegionWidth);
+ clamped_y = llclamp(y, mLumRegionTop - mLumRegionHeight, mLumRegionTop);
+ }
+
+ // update the stored RGB/HSL values using the mouse position - returns TRUE if RGB was updated
+ if ( updateRgbHslFromPoint ( clamped_x, clamped_y ) )
+ {
+ // update text entry fields
+ updateTextEntry ();
+
+ // RN: apparently changing color when dragging generates too much traffic and results in sporadic updates
+ //// commit changed color to swatch subject
+ //// REVIEW: this gets sent each time a color changes - is this okay ?
+ //if (mApplyImmediateCheck->get())
+ //{
+ // LLColorSwatchCtrl::onColorChanged ( getSwatch () );
+ //}
+ }
+ }
+
+ highlightEntry = -1;
+
+ if ( mMouseDownInSwatch )
+ {
+ getWindow()->setCursor ( UI_CURSOR_ARROWDRAG );
+
+ // if cursor if over a palette entry
+ LLRect paletteRect ( mPaletteRegionLeft,
+ mPaletteRegionTop,
+ mPaletteRegionLeft + mPaletteRegionWidth,
+ mPaletteRegionTop - mPaletteRegionHeight );
+
+ if ( paletteRect.pointInRect ( x, y ) )
+ {
+ // find row/column in palette
+ S32 xOffset = ( ( x - mPaletteRegionLeft ) * numPaletteColumns ) / mPaletteRegionWidth;
+ S32 yOffset = ( ( mPaletteRegionTop - y - 1 ) * numPaletteRows ) / mPaletteRegionHeight;
+
+ // calculate the entry 0..n-1 to highlight and set variable to next draw() picks it up
+ highlightEntry = xOffset + yOffset * numPaletteColumns;
+ }
+
+ return TRUE;
+ }
+ }
+
+ // dispatch to base class for the rest of things
+ return LLFloater::handleHover ( x, y, mask );
+}
+
+void LLFloaterColorPicker::onClose(bool app_quitting)
+{
+ //RN: this is consistent with texture picker in that closing the window leaves the current selection
+ // to change this to "close to cancel", uncomment the following line
+ //cancelSelection();
+ LLFloater::onClose(app_quitting);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// reverts state once mouse button is released
+BOOL
+LLFloaterColorPicker::
+handleMouseUp ( S32 x, S32 y, MASK mask )
+{
+ getWindow()->setCursor ( UI_CURSOR_ARROW );
+
+ if (getMouseDownInHueRegion() || getMouseDownInLumRegion())
+ {
+ if (mApplyImmediateCheck->get())
+ {
+ LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
+ }
+ }
+
+ // rect containing palette area
+ LLRect paletteRect ( mPaletteRegionLeft,
+ mPaletteRegionTop,
+ mPaletteRegionLeft + mPaletteRegionWidth,
+ mPaletteRegionTop - mPaletteRegionHeight );
+
+ if ( paletteRect.pointInRect ( x, y ) )
+ {
+ if ( mMouseDownInSwatch )
+ {
+ S32 curEntry = 0;
+ for ( S32 row = 0; row < numPaletteRows; ++row )
+ {
+ for ( S32 column = 0; column < numPaletteColumns; ++column )
+ {
+ S32 left = mPaletteRegionLeft + ( mPaletteRegionWidth * column ) / numPaletteColumns;
+ S32 top = mPaletteRegionTop - ( mPaletteRegionHeight * row ) / numPaletteRows;
+ S32 right = ( mPaletteRegionLeft + ( mPaletteRegionWidth * ( column + 1 ) ) / numPaletteColumns );
+ S32 bottom = ( mPaletteRegionTop - ( mPaletteRegionHeight * ( row + 1 ) ) / numPaletteRows );
+
+ // rect is flipped vertically when testing here
+ LLRect dropRect ( left, top, right, bottom );
+
+ if ( dropRect.pointInRect ( x, y ) )
+ {
+ if ( mPalette [ curEntry ] )
+ {
+ delete mPalette [ curEntry ];
+
+ mPalette [ curEntry ] = new LLColor4 ( getCurR (), getCurG (), getCurB (), 1.0f );
+
+ // save off color
+ std::ostringstream codec;
+ codec << "ColorPaletteEntry" << std::setfill ( '0' ) << std::setw ( 2 ) << curEntry + 1;
+ const std::string s ( codec.str () );
+ gSavedSettings.setColor4( s, *mPalette [ curEntry ] );
+ }
+ }
+
+ ++curEntry;
+ }
+ }
+ }
+ }
+
+ // mouse button not down anymore
+ setMouseDownInHueRegion ( FALSE );
+ setMouseDownInLumRegion ( FALSE );
+
+ // mouse button not down in color swatch anymore
+ mMouseDownInSwatch = false;
+
+ if (gViewerWindow->hasMouseCapture(this))
+ {
+ gViewerWindow->setMouseCapture(NULL, NULL);
+ }
+
+ // dispatch to base class for the rest of things
+ return LLFloater::handleMouseUp ( x, y, mask );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// cancel current color selection, revert to original and close picker
+void
+LLFloaterColorPicker::
+cancelSelection ()
+{
+ // restore the previous colour selection
+ setCurRgb ( getOrigR (), getOrigG (), getOrigB () );
+
+ // we're going away and when we do and the entry widgets lose focus, they do bad things so turn them off
+ enableTextCallbacks ( FALSE );
+
+ // update in world item with original color via current swatch
+ LLColorSwatchCtrl::onColorChanged( getSwatch(), LLColorSwatchCtrl::COLOR_CANCEL );
+
+ // hide picker dialog
+ this->setVisible ( FALSE );
+}
+
+void LLFloaterColorPicker::setMouseDownInHueRegion ( BOOL mouse_down_in_region )
+{
+ mMouseDownInHueRegion = mouse_down_in_region;
+ if (mouse_down_in_region)
+ {
+ if (gFocusMgr.childHasKeyboardFocus(this))
+ {
+ // get focus out of spinners so that they can update freely
+ mSelectBtn->setFocus(TRUE);
+ }
+ }
+}
+
+void LLFloaterColorPicker::setMouseDownInLumRegion ( BOOL mouse_down_in_region )
+{
+ mMouseDownInLumRegion = mouse_down_in_region;
+ if (mouse_down_in_region)
+ {
+ if (gFocusMgr.childHasKeyboardFocus(this))
+ {
+ // get focus out of spinners so that they can update freely
+ mSelectBtn->setFocus(TRUE);
+ }
+ }
+}
+
+void LLFloaterColorPicker::setMouseDownInSwatch (BOOL mouse_down_in_swatch)
+{
+ mMouseDownInSwatch = mouse_down_in_swatch;
+ if (mouse_down_in_swatch)
+ {
+ if (gFocusMgr.childHasKeyboardFocus(this))
+ {
+ // get focus out of spinners so that they can update freely
+ mSelectBtn->setFocus(TRUE);
+ }
+ }
+}
+
+void LLFloaterColorPicker::setActive(BOOL active)
+{
+ // shut down pipette tool if active
+ if (!active && mPipetteBtn->getToggleState())
+ {
+ stopUsingPipette();
+ }
+ mActive = active;
+}
+
+void LLFloaterColorPicker::stopUsingPipette()
+{
+ if (gToolMgr && gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolPipette)
+ {
+ gToolMgr->clearTransientTool();
+ }
+}