/* =========================================================================== Copyright (C) 2015 the OpenMoHAA team This file is part of OpenMoHAA source code. OpenMoHAA source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. OpenMoHAA source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenMoHAA source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ #include "ui_local.h" #include "../qcommon/localization.h" Event W_Scrollbar_Positioned ( "scrollbar_positioned", EV_DEFAULT, "i", "new_position", "Signaled when the user scrolls the view" ); Event EV_Scrollbar_Scroll ( "_scrollbar_scroll", EV_DEFAULT, "ii", "scrollrate autorepeat", "scroll the scrollbar, at the specified rate.\n" "The autorepeat is used for autoscrolling with the mouse button held down" ); CLASS_DECLARATION( UIWidget, UIVertScroll, NULL ) { { &W_LeftMouseDown, &UIVertScroll::MouseDown }, { &W_LeftMouseUp, &UIVertScroll::MouseUp }, { &W_LeftMouseDragged, &UIVertScroll::MouseDragged }, { &W_MouseEntered, &UIVertScroll::MouseEnter }, { &W_MouseExited, &UIVertScroll::MouseLeave }, { &EV_Scrollbar_Scroll, &UIVertScroll::Scroll }, { NULL, NULL } }; UIVertScroll::UIVertScroll() : m_numitems(0) , m_pageheight(0) , m_topitem(0) , m_marlett("marlett") , thumbRect(0, 0, 0, 0) , m_thumbcolor(0.15, 0.196, 0.278, 1.0) , m_solidbordercolor(0.075, 0.098, 0.139, 1.0) , m_pressed(VS_NONE) , m_frameinitted(false) { m_background_color = UColor(0.15, 0.196, 0.278, 1.0); m_foreground_color = UHudColor; } int UIVertScroll::getItemFromHeight ( float height ) { return (int)((height - 16.0 * uid.scaleRes[1]) * (float)this->m_numitems / (m_frame.size.height - 32.0 * uid.scaleRes[1])); } bool UIVertScroll::isEnoughItems ( void ) { return m_numitems > m_pageheight; } void UIVertScroll::Draw ( void ) { DrawBoxWithSolidBorder( getClientFrame(), getBackgroundColor(), m_solidbordercolor, 1, 3, m_local_alpha ); DrawArrow(0.0, "5", m_pressed == VS_UP_ARROW); DrawArrow(m_frame.size.height - getVirtualScale()[1] * 16.0, "6", m_pressed == VS_DOWN_ARROW); if (m_numitems > m_pageheight) { DrawThumb(); } } void UIVertScroll::DrawArrow ( float top, const char *text, bool pressed ) { UIRect2D arrowRect; UColor innerColor; arrowRect.pos.x = 0.0; arrowRect.pos.y = top; arrowRect.size.width = m_frame.size.width; arrowRect.size.height = getVirtualScale()[1] * 16.0; innerColor = getBackgroundColor(); m_marlett.setColor(getForegroundColor()); if (pressed) { innerColor = m_border_color.light; if (m_background_color.r != 0.0 || m_background_color.g || m_background_color.b) { m_marlett.setColor(m_border_color.light); } else { m_marlett.setColor(UColor(0.15, 0.196, 0.278, 1.0)); } } DrawBoxWithSolidBorder(arrowRect, innerColor, m_solidbordercolor, 1, 3, m_local_alpha); if (m_numitems > m_pageheight) { DrawMac3DBox(arrowRect, pressed, m_border_color, 1, m_local_alpha); } m_marlett.setAlpha(m_local_alpha); m_marlett.PrintJustified( arrowRect, m_iFontAlignmentHorizontal, m_iFontAlignmentVertical, Sys_LV_CL_ConvertString(text), getVirtualScale() ); } void UIVertScroll::DrawThumb ( void ) { UIRect2D inbarrect; float thumbHeight, thumbdiff; UColor thumbInside; thumbdiff = m_frame.size.height - getVirtualScale()[1] * 32.0; inbarrect.pos.x = 0.0; inbarrect.pos.y = getVirtualScale()[1] * 16.0; inbarrect.size.width = m_frame.size.width; inbarrect.size.height = m_frame.size.height - thumbdiff; thumbHeight = m_pageheight * thumbdiff; thumbRect.pos.x = 0.0; thumbRect.pos.y = m_topitem * thumbdiff / (float)m_numitems; thumbRect.size.width = m_frame.size.width; thumbRect.size.height = thumbHeight / (float)m_numitems; if (thumbRect.size.height < 6.0) { thumbRect.size.height = 6.0; } thumbInside = UColor(0.15, 0.196, 0.278, 1.0); if (thumbRect.pos.y + thumbRect.size.height - thumbdiff > 0.0) { thumbRect.pos.y -= thumbRect.pos.y + thumbRect.size.height - thumbdiff; } thumbRect.pos.y = thumbRect.pos.y + inbarrect.pos.y; DrawBoxWithSolidBorder(thumbRect, thumbInside, m_solidbordercolor, 1, 3, m_local_alpha); DrawMac3DBox(thumbRect, m_pressed == VS_THUMB, thumbInside, true, m_local_alpha); inbarrect.pos.x += 1.0; inbarrect.pos.y += 1.0; inbarrect.size.width -= 2.0; inbarrect.size.height -= 2.0; thumbRect.pos.x -= 1.0; thumbRect.pos.y -= 1.0; thumbRect.size.width -= 2.0; thumbRect.size.height -= 2.0; if (m_pressed == VS_PAGE_UP) { DrawBox( 0.0, inbarrect.pos.y, m_frame.size.width, thumbRect.pos.y - inbarrect.pos.y, m_border_color.light, m_local_alpha ); } else if (m_pressed == VS_PAGE_DOWN) { DrawBox( 0.0, thumbRect.pos.y + thumbRect.size.height, m_frame.size.width, inbarrect.pos.y + inbarrect.size.height - (thumbRect.pos.y + thumbRect.size.height), m_border_color.light, m_local_alpha ); } } void UIVertScroll::MouseDown ( Event *ev ) { UIPoint2D p; int scrollrate; scrollrate = 0; p.x = ev->GetFloat(1) - m_screenframe.pos.x; p.y = ev->GetFloat(2) - m_screenframe.pos.y; m_pressed = VS_NONE; if (p.x < 0 || p.y < 0) { return; } if (p.x > m_frame.size.width || p.y > m_frame.size.height) { return; } if (m_numitems <= m_pageheight) { return; } if (p.y >= 16.0) { if (m_frame.size.height - 16.0 >= p.y) { if (thumbRect.pos.y > p.y) { m_pressed = VS_PAGE_UP; scrollrate = -m_pageheight; } else { if (thumbRect.pos.y + thumbRect.size.height > p.y) { m_pressed = VS_THUMB; m_dragThumbState.itemOffset = m_topitem - getItemFromHeight(p.y); m_dragThumbState.orgItem = m_topitem; uWinMan.setFirstResponder(this); } else { m_pressed = VS_PAGE_DOWN; scrollrate = m_pageheight; } } if (!scrollrate) { return; } } else { m_pressed = VS_DOWN_ARROW; scrollrate = 1; } } else { m_pressed = VS_UP_ARROW; scrollrate = -1; } Event* newev = new Event(EV_Scrollbar_Scroll); newev->AddInteger(scrollrate); newev->AddInteger(0); CancelEventsOfType(EV_Scrollbar_Scroll); PostEvent(newev, 0); uWinMan.setFirstResponder(this); } void UIVertScroll::MouseUp ( Event *ev ) { CancelEventsOfType(EV_Scrollbar_Scroll); if (uWinMan.getFirstResponder() == this) { uWinMan.setFirstResponder(NULL); } m_pressed = VS_NONE; } void UIVertScroll::MouseDragged ( Event *ev ) { UIPoint2D p; if (m_pressed != VS_THUMB) { return; } p.x = ev->GetFloat(1) - m_screenframe.pos.x; p.y = ev->GetFloat(2); if (p.x < -24.0 || p.x > m_frame.size.width + 24.0) { AttemptScrollTo(m_dragThumbState.orgItem); } else { AttemptScrollTo(m_dragThumbState.itemOffset + getItemFromHeight(p.y - m_screenframe.pos.y)); } } void UIVertScroll::MouseEnter ( Event *ev ) { // Fixed in OPM // Why should hovering over the scrollbar activate the control it's on? // This is more disorienting than useful, also no sane window manager // works like this. Simply clicking into it should be sufficient. //uWinMan.ActivateControl(this); } void UIVertScroll::MouseLeave ( Event *ev ) { } void UIVertScroll::Scroll ( Event *ev ) { if (AttemptScrollTo(m_topitem + ev->GetInteger(1))) { float delay = 0.2; if (ev->GetInteger(2)) { delay = 0.1; } Event *newev = new Event(EV_Scrollbar_Scroll); newev->AddInteger(ev->GetInteger(1)); newev->AddInteger(0); PostEvent(newev, delay); } } bool UIVertScroll::AttemptScrollTo ( int to ) { int besttopitem; if (to < 0) { to = 0; } besttopitem = m_numitems - m_pageheight; if (besttopitem < 0) { besttopitem = 0; } if (to > besttopitem) { to = besttopitem; } if (to == m_topitem) { return false; } m_topitem = to; Event ev(W_Scrollbar_Positioned); ev.AddInteger(m_topitem); SendSignal(ev); return true; } void UIVertScroll::setNumItems ( int i ) { m_numitems = i; } void UIVertScroll::setPageHeight ( int i ) { m_pageheight = i; } void UIVertScroll::setTopItem ( int i ) { if (i >= 0) { m_topitem = i; } else { m_topitem = 0; } } int UIVertScroll::getTopItem ( void ) { return m_topitem; } int UIVertScroll::getPageHeight ( void ) { return m_pageheight; } int UIVertScroll::getNumItems ( void ) { return m_numitems; } void UIVertScroll::setThumbColor ( const UColor& thumb ) { m_thumbcolor = thumb; } void UIVertScroll::setSolidBorderColor ( const UColor& col ) { m_solidbordercolor = col; } void UIVertScroll::InitFrameAlignRight ( UIWidget *parent, float fWidthPadding, float fHeightPadding ) { UIRect2D frame, frameOut; frame = parent->getClientFrame(); frameOut.pos.x = frame.pos.x + frame.size.width - (fWidthPadding + 16.0) * getVirtualScale()[0]; frameOut.pos.y = fHeightPadding * getVirtualScale()[1]; frameOut.size.width = getVirtualScale()[0] * 16.0; frameOut.size.height = frame.size.height - (fHeightPadding * 2) * getVirtualScale()[1]; if (!m_frameinitted) { InitFrame(parent, frameOut, -1, "verdana-12"); m_frameinitted = true; } else { setFrame(frameOut); } } void UIVertScroll::FrameInitialized() { UIWidget::FrameInitialized(); }