PageRenderTime 89ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/src/gui/widgets/tabs/tab.cpp

https://gitlab.com/akkoteru/manaplus
C++ | 480 lines | 351 code | 59 blank | 70 comment | 53 complexity | 608e3937496c214ba3671476850f3c26 MD5 | raw file
  1. /*
  2. * The ManaPlus Client
  3. * Copyright (C) 2008-2009 The Mana World Development Team
  4. * Copyright (C) 2009-2010 The Mana Developers
  5. * Copyright (C) 2011-2016 The ManaPlus Developers
  6. *
  7. * This file is part of The ManaPlus Client.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * any later version.
  13. *
  14. * This program 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
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. /* _______ __ __ __ ______ __ __ _______ __ __
  23. * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
  24. * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
  25. * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
  26. * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
  27. * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
  28. * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
  29. *
  30. * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
  31. *
  32. *
  33. * Per Larsson a.k.a finalman
  34. * Olof Naessén a.k.a jansem/yakslem
  35. *
  36. * Visit: http://guichan.sourceforge.net
  37. *
  38. * License: (BSD)
  39. * Redistribution and use in source and binary forms, with or without
  40. * modification, are permitted provided that the following conditions
  41. * are met:
  42. * 1. Redistributions of source code must retain the above copyright
  43. * notice, this list of conditions and the following disclaimer.
  44. * 2. Redistributions in binary form must reproduce the above copyright
  45. * notice, this list of conditions and the following disclaimer in
  46. * the documentation and/or other materials provided with the
  47. * distribution.
  48. * 3. Neither the name of Guichan nor the names of its contributors may
  49. * be used to endorse or promote products derived from this software
  50. * without specific prior written permission.
  51. *
  52. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  53. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  54. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  55. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  56. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  57. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  58. * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  59. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  60. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  61. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  62. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  63. */
  64. #include "gui/widgets/tabs/tab.h"
  65. #include "settings.h"
  66. #include "gui/gui.h"
  67. #include "gui/skin.h"
  68. #include "gui/widgets/label.h"
  69. #include "gui/widgets/tabbedarea.h"
  70. #include "render/vertexes/imagecollection.h"
  71. #include "resources/imagerect.h"
  72. #include "resources/image/image.h"
  73. #include "utils/delete2.h"
  74. #include "debug.h"
  75. int Tab::mInstances = 0;
  76. float Tab::mAlpha = 1.0;
  77. namespace
  78. {
  79. static std::string const data[Tab::TAB_COUNT] =
  80. {
  81. "tab.xml",
  82. "tab_highlighted.xml",
  83. "tab_selected.xml",
  84. "tab_unused.xml"
  85. };
  86. } // namespace
  87. Skin *Tab::tabImg[Tab::TAB_COUNT];
  88. Tab::Tab(const Widget2 *const widget) :
  89. BasicContainer(widget),
  90. MouseListener(),
  91. WidgetListener(),
  92. mLabel(new Label(this)),
  93. mTabbedArea(nullptr),
  94. mTabColor(&getThemeColor(ThemeColorId::TAB)),
  95. mTabOutlineColor(&getThemeColor(ThemeColorId::TAB_OUTLINE)),
  96. mTabHighlightedColor(&getThemeColor(ThemeColorId::TAB_HIGHLIGHTED)),
  97. mTabHighlightedOutlineColor(&getThemeColor(
  98. ThemeColorId::TAB_HIGHLIGHTED_OUTLINE)),
  99. mTabSelectedColor(&getThemeColor(ThemeColorId::TAB_SELECTED)),
  100. mTabSelectedOutlineColor(&getThemeColor(
  101. ThemeColorId::TAB_SELECTED_OUTLINE)),
  102. mFlashColor(&getThemeColor(ThemeColorId::TAB_FLASH)),
  103. mFlashOutlineColor(&getThemeColor(ThemeColorId::TAB_FLASH_OUTLINE)),
  104. mPlayerFlashColor(&getThemeColor(ThemeColorId::TAB_PLAYER_FLASH)),
  105. mPlayerFlashOutlineColor(&getThemeColor(
  106. ThemeColorId::TAB_PLAYER_FLASH_OUTLINE)),
  107. mFlash(0),
  108. mVertexes(new ImageCollection),
  109. mImage(nullptr),
  110. mMode(0),
  111. mLabelMode(-1),
  112. mHasMouse(false)
  113. {
  114. init();
  115. }
  116. Tab::~Tab()
  117. {
  118. if (gui)
  119. gui->removeDragged(this);
  120. mInstances--;
  121. if (mInstances == 0 && theme)
  122. {
  123. for (int mode = 0; mode < TAB_COUNT; mode ++)
  124. theme->unload(tabImg[mode]);
  125. }
  126. delete2(mLabel);
  127. if (mImage)
  128. {
  129. mImage->decRef();
  130. mImage = nullptr;
  131. }
  132. delete2(mVertexes);
  133. }
  134. void Tab::init()
  135. {
  136. addMouseListener(this);
  137. setFocusable(false);
  138. setFrameSize(0);
  139. mFlash = 0;
  140. addWidgetListener(this);
  141. if (mInstances == 0)
  142. {
  143. // Load the skin
  144. if (theme)
  145. {
  146. for (int mode = 0; mode < TAB_COUNT; mode ++)
  147. tabImg[mode] = theme->load(data[mode], "tab.xml");
  148. }
  149. updateAlpha();
  150. }
  151. mInstances++;
  152. add(mLabel);
  153. const Skin *const skin = tabImg[TAB_STANDARD];
  154. if (!skin)
  155. return;
  156. const int padding = skin->getPadding();
  157. mLabel->setPosition(padding, padding);
  158. }
  159. void Tab::updateAlpha()
  160. {
  161. const float alpha = std::max(settings.guiAlpha,
  162. theme->getMinimumOpacity());
  163. if (alpha != mAlpha)
  164. {
  165. mAlpha = alpha;
  166. for (int a = 0; a < 9; a++)
  167. {
  168. for (int t = 0; t < TAB_COUNT; t++)
  169. {
  170. Skin *const skin = tabImg[t];
  171. if (skin)
  172. {
  173. const ImageRect &rect = skin->getBorder();
  174. Image *const image = rect.grid[a];
  175. if (image)
  176. image->setAlpha(mAlpha);
  177. }
  178. }
  179. }
  180. }
  181. }
  182. void Tab::draw(Graphics *const graphics)
  183. {
  184. BLOCK_START("Tab::draw")
  185. int mode = TAB_STANDARD;
  186. // check which type of tab to draw
  187. if (mTabbedArea)
  188. {
  189. int labelMode = mFlash;
  190. if (mTabbedArea->isTabSelected(this))
  191. {
  192. labelMode = 3;
  193. mode = TAB_SELECTED;
  194. // if tab is selected, it doesnt need to highlight activity
  195. mFlash = 0;
  196. }
  197. else if (!labelMode)
  198. {
  199. if (mHasMouse)
  200. {
  201. labelMode = 4;
  202. mode = TAB_HIGHLIGHTED;
  203. }
  204. }
  205. else if (mHasMouse)
  206. {
  207. mode = TAB_HIGHLIGHTED;
  208. }
  209. // mRedraw need here because no other way to say label to change color
  210. // +++ text from label must be moved to tab itself
  211. if (labelMode != mLabelMode || mRedraw)
  212. {
  213. mLabelMode = labelMode;
  214. switch (labelMode)
  215. {
  216. case 0: // default state
  217. default:
  218. mLabel->setForegroundColorAll(*mTabColor,
  219. *mTabOutlineColor);
  220. break;
  221. case 1: // mFlash == 1
  222. mLabel->setForegroundColorAll(*mFlashColor,
  223. *mFlashOutlineColor);
  224. break;
  225. case 2: // mFlash == 2
  226. mLabel->setForegroundColorAll(*mPlayerFlashColor,
  227. *mPlayerFlashOutlineColor);
  228. break;
  229. case 3: // mTabbedArea->isTabSelected(this)
  230. mLabel->setForegroundColorAll(*mTabSelectedColor,
  231. *mTabSelectedOutlineColor);
  232. break;
  233. case 4: // mHasMouse
  234. mLabel->setForegroundColorAll(*mTabHighlightedColor,
  235. *mTabHighlightedOutlineColor);
  236. break;
  237. }
  238. }
  239. }
  240. const Skin *const skin = tabImg[mode];
  241. if (!skin)
  242. {
  243. BLOCK_END("Tab::draw")
  244. return;
  245. }
  246. updateAlpha();
  247. const ImageRect &rect = skin->getBorder();
  248. if (mRedraw || mode != mMode || graphics->getRedraw())
  249. {
  250. mMode = mode;
  251. mRedraw = false;
  252. mVertexes->clear();
  253. graphics->calcWindow(mVertexes,
  254. 0, 0,
  255. mDimension.width, mDimension.height,
  256. rect);
  257. if (mImage)
  258. {
  259. const Skin *const skin1 = tabImg[TAB_STANDARD];
  260. if (skin1)
  261. {
  262. const int padding = skin1->getPadding();
  263. graphics->calcTileCollection(mVertexes,
  264. mImage,
  265. padding,
  266. padding);
  267. }
  268. }
  269. graphics->finalize(mVertexes);
  270. }
  271. graphics->drawTileCollection(mVertexes);
  272. drawChildren(graphics);
  273. BLOCK_END("Tab::draw")
  274. }
  275. void Tab::safeDraw(Graphics *const graphics)
  276. {
  277. BLOCK_START("Tab::draw")
  278. int mode = TAB_STANDARD;
  279. // check which type of tab to draw
  280. if (mTabbedArea)
  281. {
  282. int labelMode = mFlash;
  283. if (mTabbedArea->isTabSelected(this))
  284. {
  285. labelMode = 3;
  286. mode = TAB_SELECTED;
  287. // if tab is selected, it doesnt need to highlight activity
  288. mFlash = 0;
  289. }
  290. else if (!labelMode)
  291. {
  292. if (mHasMouse)
  293. {
  294. labelMode = 4;
  295. mode = TAB_HIGHLIGHTED;
  296. }
  297. }
  298. else if (mHasMouse)
  299. {
  300. mode = TAB_HIGHLIGHTED;
  301. }
  302. if (labelMode != mLabelMode)
  303. {
  304. mLabelMode = labelMode;
  305. switch (labelMode)
  306. {
  307. case 0: // default state
  308. default:
  309. mLabel->setForegroundColorAll(*mTabColor,
  310. *mTabOutlineColor);
  311. break;
  312. case 1: // mFlash == 1
  313. mLabel->setForegroundColorAll(*mFlashColor,
  314. *mFlashOutlineColor);
  315. break;
  316. case 2: // mFlash == 2
  317. mLabel->setForegroundColorAll(*mPlayerFlashColor,
  318. *mPlayerFlashOutlineColor);
  319. break;
  320. case 3: // mTabbedArea->isTabSelected(this)
  321. mLabel->setForegroundColorAll(*mTabSelectedColor,
  322. *mTabSelectedOutlineColor);
  323. break;
  324. case 4: // mHasMouse
  325. mLabel->setForegroundColorAll(*mTabHighlightedColor,
  326. *mTabHighlightedOutlineColor);
  327. break;
  328. }
  329. }
  330. }
  331. const Skin *const skin = tabImg[mode];
  332. if (!skin)
  333. {
  334. BLOCK_END("Tab::draw")
  335. return;
  336. }
  337. updateAlpha();
  338. graphics->drawImageRect(0, 0,
  339. mDimension.width, mDimension.height,
  340. skin->getBorder());
  341. if (mImage)
  342. {
  343. const Skin *const skin1 = tabImg[TAB_STANDARD];
  344. if (skin1)
  345. {
  346. const int padding = skin1->getPadding();
  347. graphics->drawImage(mImage, padding, padding);
  348. }
  349. }
  350. safeDrawChildren(graphics);
  351. BLOCK_END("Tab::draw")
  352. }
  353. void Tab::widgetResized(const Event &event A_UNUSED)
  354. {
  355. mRedraw = true;
  356. }
  357. void Tab::widgetMoved(const Event &event A_UNUSED)
  358. {
  359. mRedraw = true;
  360. }
  361. void Tab::setLabelFont(Font *const font)
  362. {
  363. if (!mLabel)
  364. return;
  365. mLabel->setFont(font);
  366. mLabel->adjustSize();
  367. adjustSize();
  368. mRedraw = true;
  369. }
  370. void Tab::adjustSize()
  371. {
  372. const Skin *const skin = tabImg[TAB_STANDARD];
  373. if (!skin)
  374. return;
  375. const int pad2 = skin->getPadding() * 2;
  376. if (mImage)
  377. {
  378. const SDL_Rect &rect = mImage->mBounds;
  379. setSize(rect.w + pad2, rect.h + pad2);
  380. }
  381. else
  382. {
  383. setSize(mLabel->getWidth() + pad2,
  384. mLabel->getHeight() + pad2);
  385. }
  386. if (mTabbedArea)
  387. mTabbedArea->adjustTabPositions();
  388. }
  389. void Tab::setTabbedArea(TabbedArea* tabbedArea)
  390. {
  391. mTabbedArea = tabbedArea;
  392. }
  393. TabbedArea* Tab::getTabbedArea() const
  394. {
  395. return mTabbedArea;
  396. }
  397. void Tab::setCaption(const std::string &caption)
  398. {
  399. mLabel->setCaption(caption);
  400. mLabel->adjustSize();
  401. adjustSize();
  402. }
  403. void Tab::setImage(Image *const image)
  404. {
  405. if (mImage)
  406. mImage->decRef();
  407. mImage = image;
  408. adjustSize();
  409. }
  410. const std::string &Tab::getCaption() const
  411. {
  412. return mLabel->getCaption();
  413. }
  414. void Tab::mouseEntered(MouseEvent& event A_UNUSED)
  415. {
  416. mHasMouse = true;
  417. }
  418. void Tab::mouseExited(MouseEvent& event A_UNUSED)
  419. {
  420. mHasMouse = false;
  421. }