llcolorswatch.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. /**
  2. * @file llcolorswatch.cpp
  3. * @brief LLColorSwatch class implementation
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llcolorswatch.h"
  34. #include "llbutton.h"
  35. #include "llrender.h"
  36. #include "lltextbox.h"
  37. #include "llviewborder.h"
  38. #include "llwindow.h"
  39. #include "llagent.h"
  40. #include "llfloatercolorpicker.h"
  41. #include "llviewertexturelist.h"
  42. static const std::string LL_COLOR_SWATCH_CTRL_TAG = "color_swatch";
  43. static LLRegisterWidget<LLColorSwatchCtrl> r(LL_COLOR_SWATCH_CTRL_TAG);
  44. LLColorSwatchCtrl::LLColorSwatchCtrl(const std::string& name,
  45. const LLRect& rect,
  46. const LLColor4& color,
  47. void (*commit_callback)(LLUICtrl* ctrl,
  48. void* userdata),
  49. void* userdata)
  50. : LLUICtrl(name, rect, true, commit_callback, userdata,
  51. FOLLOWS_LEFT | FOLLOWS_TOP),
  52. mValid(true),
  53. mColor(color),
  54. mBorderColor(LLUI::sDefaultHighlightLight),
  55. mCanApplyImmediately(false),
  56. mOnCancelCallback(NULL),
  57. mOnSelectCallback(NULL)
  58. {
  59. mCaption = new LLTextBox(name,LLRect(0, gBtnHeightSmall,
  60. getRect().getWidth(), 0),
  61. name, LLFontGL::getFontSansSerifSmall());
  62. mCaption->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
  63. addChild(mCaption);
  64. // Scalable UI made this off-by-one, I do not know why. JC
  65. LLRect border_rect(0, getRect().getHeight() - 1,
  66. getRect().getWidth() - 1, 0);
  67. border_rect.mBottom += gBtnHeightSmall;
  68. mBorder = new LLViewBorder(std::string("border"), border_rect,
  69. LLViewBorder::BEVEL_IN);
  70. addChild(mBorder);
  71. mAlphaGradientImage = LLUI::getUIImage("color_swatch_alpha.tga");
  72. }
  73. LLColorSwatchCtrl::LLColorSwatchCtrl(const std::string& name,
  74. const LLRect& rect,
  75. const std::string& label,
  76. const LLColor4& color,
  77. void (*commit_callback)(LLUICtrl* ctrl,
  78. void* userdata),
  79. void* userdata)
  80. : LLUICtrl(name, rect, true, commit_callback, userdata,
  81. FOLLOWS_LEFT | FOLLOWS_TOP),
  82. mValid(true),
  83. mColor(color),
  84. mBorderColor(LLUI::sDefaultHighlightLight),
  85. mCanApplyImmediately(false),
  86. mOnCancelCallback(NULL),
  87. mOnSelectCallback(NULL)
  88. {
  89. mCaption = new LLTextBox(label, LLRect(0, gBtnHeightSmall,
  90. getRect().getWidth(), 0),
  91. label, LLFontGL::getFontSansSerifSmall());
  92. mCaption->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
  93. addChild(mCaption);
  94. // Scalable UI made this off-by-one, I do not know why. JC
  95. LLRect border_rect(0, getRect().getHeight() - 1,
  96. getRect().getWidth() - 1, 0);
  97. border_rect.mBottom += gBtnHeightSmall;
  98. mBorder = new LLViewBorder(std::string("border"), border_rect,
  99. LLViewBorder::BEVEL_IN);
  100. addChild(mBorder);
  101. mAlphaGradientImage = LLUI::getUIImage("color_swatch_alpha.tga");
  102. }
  103. //virtual
  104. LLColorSwatchCtrl::~LLColorSwatchCtrl()
  105. {
  106. // Parent dialog is destroyed so we are too and we need to cancel selection
  107. LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
  108. if (pickerp)
  109. {
  110. pickerp->cancelSelection();
  111. pickerp->close();
  112. }
  113. mAlphaGradientImage = NULL;
  114. }
  115. //virtual
  116. bool LLColorSwatchCtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
  117. {
  118. return handleMouseDown(x, y, mask);
  119. }
  120. //virtual
  121. bool LLColorSwatchCtrl::handleHover(S32 x, S32 y, MASK mask)
  122. {
  123. gWindowp->setCursor(UI_CURSOR_HAND);
  124. return true;
  125. }
  126. //virtual
  127. bool LLColorSwatchCtrl::handleUnicodeCharHere(llwchar uni_char)
  128. {
  129. if (uni_char == ' ')
  130. {
  131. showPicker(true);
  132. }
  133. return LLUICtrl::handleUnicodeCharHere(uni_char);
  134. }
  135. // Forces color of this swatch and any associated floater to the input value,
  136. // if currently invalid
  137. void LLColorSwatchCtrl::setOriginal(const LLColor4& color)
  138. {
  139. mColor = color;
  140. LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
  141. if (pickerp)
  142. {
  143. pickerp->setOrigRgb(mColor.mV[VRED], mColor.mV[VGREEN],
  144. mColor.mV[VBLUE]);
  145. }
  146. }
  147. void LLColorSwatchCtrl::set(const LLColor4& color, bool update_picker,
  148. bool from_event)
  149. {
  150. mColor = color;
  151. LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
  152. if (pickerp && update_picker)
  153. {
  154. pickerp->setCurRgb(mColor.mV[VRED], mColor.mV[VGREEN],
  155. mColor.mV[VBLUE]);
  156. }
  157. if (!from_event)
  158. {
  159. setControlValue(mColor.getValue());
  160. }
  161. }
  162. void LLColorSwatchCtrl::setLabel(const std::string& label)
  163. {
  164. mCaption->setText(label);
  165. }
  166. void LLColorSwatchCtrl::setFallbackImageName(const std::string& image_name)
  167. {
  168. mFallbackImage =
  169. LLViewerTextureManager::getFetchedTextureFromFile(image_name,
  170. MIPMAP_YES,
  171. LLGLTexture::BOOST_PREVIEW,
  172. LLViewerTexture::LOD_TEXTURE);
  173. }
  174. //virtual
  175. bool LLColorSwatchCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
  176. {
  177. // Route future Mouse messages here preemptively (release on mouse up).
  178. // No handler is needed for capture lost since this object has no state
  179. // that depends on it.
  180. gFocusMgr.setMouseCapture(this);
  181. return true;
  182. }
  183. //virtual
  184. bool LLColorSwatchCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
  185. {
  186. // We only handle the click if the click both started and ended within us
  187. if (hasMouseCapture())
  188. {
  189. // Release the mouse
  190. gFocusMgr.setMouseCapture(NULL);
  191. // If mouseup in the widget, it has been clicked
  192. if (pointInView(x, y))
  193. {
  194. llassert(getEnabled());
  195. llassert(getVisible());
  196. showPicker(false);
  197. }
  198. }
  199. return true;
  200. }
  201. // Assumes GL state is set for 2D
  202. //virtual
  203. void LLColorSwatchCtrl::draw()
  204. {
  205. mBorder->setKeyboardFocusHighlight(hasFocus());
  206. // Draw border
  207. LLRect border(0, getRect().getHeight(), getRect().getWidth(),
  208. gBtnHeightSmall);
  209. gl_rect_2d(border, mBorderColor, false);
  210. LLRect interior = border;
  211. interior.stretch(-1);
  212. // Check state
  213. if (mValid || gAgent.isGodlikeWithoutAdminMenuFakery())
  214. {
  215. // Draw the color swatch
  216. gl_rect_2d_checkerboard(interior);
  217. gl_rect_2d(interior, mColor, true);
  218. LLColor4 opaque_color = mColor;
  219. opaque_color.mV[VALPHA] = 1.f;
  220. gGL.color4fv(opaque_color.mV);
  221. if (mAlphaGradientImage.notNull())
  222. {
  223. gGL.pushMatrix();
  224. {
  225. mAlphaGradientImage->draw(interior, mColor);
  226. }
  227. gGL.popMatrix();
  228. }
  229. }
  230. else if (mFallbackImage.notNull())
  231. {
  232. if (mFallbackImage->getComponents() == 4)
  233. {
  234. gl_rect_2d_checkerboard(interior);
  235. }
  236. gl_draw_scaled_image(interior.mLeft, interior.mBottom,
  237. interior.getWidth(), interior.getHeight(),
  238. mFallbackImage);
  239. mFallbackImage->addTextureStats((F32)(interior.getWidth() *
  240. interior.getHeight()));
  241. }
  242. else
  243. {
  244. // Draw grey and an X
  245. gl_rect_2d(interior, LLColor4::grey, true);
  246. gl_draw_x(interior, LLColor4::black);
  247. }
  248. LLUICtrl::draw();
  249. }
  250. //virtual
  251. void LLColorSwatchCtrl::setEnabled(bool enabled)
  252. {
  253. mCaption->setEnabled(enabled);
  254. LLView::setEnabled(enabled);
  255. if (!enabled)
  256. {
  257. LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
  258. if (pickerp)
  259. {
  260. pickerp->cancelSelection();
  261. pickerp->close();
  262. }
  263. }
  264. }
  265. //virtual
  266. void LLColorSwatchCtrl::setValue(const LLSD& value)
  267. {
  268. set(LLColor4(value), true, true);
  269. }
  270. // Called (infrequently) when the color changes so the subject of the swatch
  271. // can be updated.
  272. void LLColorSwatchCtrl::onColorChanged(void* data, EColorPickOp pick_op)
  273. {
  274. LLColorSwatchCtrl* subject = (LLColorSwatchCtrl*)data;
  275. if (!subject)
  276. {
  277. return;
  278. }
  279. LLFloaterColorPicker* pickerp =
  280. (LLFloaterColorPicker*)subject->mPickerHandle.get();
  281. if (!pickerp)
  282. {
  283. return;
  284. }
  285. // Move color across from selector to internal widget storage, keeping
  286. // current alpha.
  287. LLColor4 new_color(pickerp->getCurR(), pickerp->getCurG(),
  288. pickerp->getCurB(), subject->mColor.mV[VALPHA]);
  289. subject->mColor = new_color;
  290. subject->setControlValue(new_color.getValue());
  291. if (pick_op == COLOR_CANCEL && subject->mOnCancelCallback)
  292. {
  293. subject->mOnCancelCallback(subject, subject->mCallbackUserData);
  294. }
  295. else if (pick_op == COLOR_SELECT && subject->mOnSelectCallback)
  296. {
  297. subject->mOnSelectCallback(subject, subject->mCallbackUserData);
  298. }
  299. else
  300. {
  301. // Just commit the change
  302. subject->onCommit();
  303. }
  304. }
  305. void LLColorSwatchCtrl::setValid(bool valid)
  306. {
  307. mValid = valid;
  308. LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
  309. if (pickerp)
  310. {
  311. pickerp->setActive(valid);
  312. }
  313. }
  314. void LLColorSwatchCtrl::showPicker(bool take_focus)
  315. {
  316. LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
  317. if (!pickerp)
  318. {
  319. pickerp = new LLFloaterColorPicker(this, mCanApplyImmediately);
  320. if (gFloaterViewp)
  321. {
  322. LLFloater* parentp = gFloaterViewp->getParentFloater(this);
  323. if (parentp)
  324. {
  325. parentp->addDependentFloater(pickerp);
  326. }
  327. }
  328. mPickerHandle = pickerp->getHandle();
  329. }
  330. // Initialize picker with current color
  331. pickerp->initUI(mColor.mV[VRED], mColor.mV[VGREEN], mColor.mV[VBLUE]);
  332. // Display it
  333. pickerp->showUI();
  334. if (take_focus)
  335. {
  336. pickerp->setFocus(true);
  337. }
  338. }
  339. //virtual
  340. const std::string& LLColorSwatchCtrl::getTag() const
  341. {
  342. return LL_COLOR_SWATCH_CTRL_TAG;
  343. }
  344. //virtual
  345. LLXMLNodePtr LLColorSwatchCtrl::getXML(bool save_children) const
  346. {
  347. LLXMLNodePtr node = LLUICtrl::getXML();
  348. node->setName(LL_COLOR_SWATCH_CTRL_TAG);
  349. node->createChild("initial_color", true)->setFloatValue(4, mColor.mV);
  350. node->createChild("border_color", true)->setFloatValue(4, mBorderColor.mV);
  351. if (mCaption)
  352. {
  353. node->createChild("label", true)->setStringValue(mCaption->getText());
  354. }
  355. node->createChild("can_apply_immediately", true)->setBoolValue(mCanApplyImmediately);
  356. return node;
  357. }
  358. //static
  359. LLView* LLColorSwatchCtrl::fromXML(LLXMLNodePtr node, LLView* parent,
  360. LLUICtrlFactory* factory)
  361. {
  362. std::string name = "colorswatch";
  363. node->getAttributeString("name", name);
  364. std::string label;
  365. node->getAttributeString("label", label);
  366. LLColor4 color = LLColor4::white;
  367. node->getAttributeColor("initial_color", color);
  368. LLRect rect;
  369. createRect(node, rect, parent, LLRect());
  370. bool can_apply_immediately = false;
  371. node->getAttributeBool("can_apply_immediately", can_apply_immediately);
  372. LLUICtrlCallback callback = NULL;
  373. if (label.empty())
  374. {
  375. label.assign(node->getValue());
  376. }
  377. LLColorSwatchCtrl* self = new LLColorSwatchCtrl(name, rect, label, color,
  378. callback, NULL);
  379. self->setCanApplyImmediately(can_apply_immediately);
  380. self->initFromXML(node, parent);
  381. return self;
  382. }