/* =========================================================================== 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" Event W_HScrollbar_Positioned ( "hscrollbar_positioned", EV_DEFAULT, "i", "new_position", "Signaled when the user scrolls the view" ); Event EV_HScrollbar_Scroll ( "_hscrollbar_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, UIHorizScroll, NULL) { {&W_LeftMouseDown, &UIHorizScroll::MouseDown }, {&W_LeftMouseUp, &UIHorizScroll::MouseUp }, {&W_LeftMouseDragged, &UIHorizScroll::MouseDragged}, {&W_MouseEntered, &UIHorizScroll::MouseEnter }, {&W_MouseExited, &UIHorizScroll::MouseLeave }, {&EV_HScrollbar_Scroll, &UIHorizScroll::Scroll }, {NULL, NULL } }; UIHorizScroll::UIHorizScroll() : m_numitems(0) , m_pagewidth(0) , m_topitem(0) , m_marlett("marlett") , thumbRect(0, 0, 0, 0) , m_pressed(VS_NONE) , m_frameinitted(false) , m_thumbcolor(UDarkGrey) , m_solidbordercolor(UBlack) {} void UIHorizScroll::DrawArrow(float top, const char *text, bool pressed) { UIRect2D arrowRect(top, 0, m_frame.size.height, m_vVirtualScale[1] * 16.f); UColor innerColor(m_background_color); m_marlett.setColor(m_foreground_color); if (pressed) { if (!m_background_color.r && !m_background_color.g && !m_background_color.b) { m_marlett.setColor(UGrey); } else { m_marlett.setColor(m_border_color.light); } } DrawBoxWithSolidBorder(arrowRect, innerColor, m_solidbordercolor, 1, 3, m_local_alpha); if (m_numitems > m_pagewidth) { DrawMac3DBox(arrowRect, pressed, m_border_color, 1, m_local_alpha); } m_marlett.PrintJustified( arrowRect, m_iFontAlignmentHorizontal, m_iFontAlignmentVertical, text, m_bVirtual ? m_vVirtualScale : NULL ); } void UIHorizScroll::DrawThumb(void) { UIRect2D inbarrect; float thumbWidth; float thumbdiff; UColor thumbInside; thumbdiff = m_frame.size.width - m_vVirtualScale[1] * 32.f; inbarrect.pos.x = m_vVirtualScale[1] * 16.0; inbarrect.pos.y = 0; inbarrect.size.width = thumbdiff; inbarrect.size.height = m_frame.size.height; thumbRect.pos.x = m_topitem * thumbdiff / m_numitems; thumbRect.pos.y = 0.0; thumbRect.size.width = m_pagewidth * thumbdiff / m_numitems; if (thumbRect.size.width < 6.f) { thumbRect.size.width = 6.f; } thumbRect.size.height = m_frame.size.height; thumbInside = UDarkGrey; thumbWidth = thumbRect.pos.x + thumbRect.size.width - thumbdiff; if (m_pressed == VS_THUMB) { thumbInside = UColor(-0.5f, -0.5f, -0.5f, thumbInside.a + 1.f); if (thumbInside.r >= 0) { thumbInside.r = 0; } thumbInside.g = Q_max(thumbInside.g, 0); thumbInside.b = Q_max(thumbInside.b, 0); } if (thumbWidth > 0) { thumbRect.pos.x -= thumbWidth; } thumbRect.pos.x += inbarrect.pos.x; DrawBoxWithSolidBorder(thumbRect, thumbInside, m_solidbordercolor, 1, 3, m_local_alpha); DrawMac3DBox(thumbRect, false, UBorderColor(thumbInside), true, m_local_alpha); inbarrect.pos.x += 1; inbarrect.pos.y += 1; inbarrect.size.width += -2; inbarrect.size.height += -2; thumbRect.pos.x += -1; thumbRect.pos.y += -1; thumbRect.size.width += -2; thumbRect.size.height += 2; switch (m_pressed) { case VS_PAGE_UP: DrawBox( inbarrect.pos.x, 0, thumbRect.pos.x - inbarrect.pos.x, m_frame.size.height, m_border_color.dark, m_local_alpha ); break; case VS_PAGE_DOWN: DrawBox( thumbRect.pos.x + thumbRect.size.width, 0, inbarrect.pos.x + inbarrect.size.width - (thumbRect.pos.x + thumbRect.size.width), m_frame.size.height, m_border_color.dark, m_local_alpha ); break; default: break; } } void UIHorizScroll::Draw(void) { UIRect2D arrowRect; UColor innerColor(0, 0, 0, 1); arrowRect = getClientFrame(); DrawBoxWithSolidBorder(arrowRect, m_background_color, m_solidbordercolor, 1, 3, m_local_alpha); DrawArrow(0, "3", m_pressed == VS_UP_ARROW); DrawArrow(m_frame.size.width - m_vVirtualScale[1] * 16.f, "4", m_pressed = VS_DOWN_ARROW); if (m_numitems > m_pagewidth) { DrawThumb(); } } void UIHorizScroll::Scroll(Event *ev) { if (!AttemptScrollTo(m_topitem + ev->GetInteger(1))) { return; } float delay = 0.2f; if (ev->GetInteger(2)) { delay = 0.1f; } Event event(EV_HScrollbar_Scroll); event.AddInteger(ev->GetInteger(1)); event.AddInteger(0); PostEvent(event, delay); } bool UIHorizScroll::AttemptScrollTo(int to) { int besttopitem; if (to < 0) { to = 0; } besttopitem = m_numitems - m_pagewidth; if (besttopitem < 0) { besttopitem = 0; } if (to > besttopitem) { to = besttopitem; } if (to == m_topitem) { return false; } Event ev(W_HScrollbar_Positioned); ev.AddInteger(m_topitem); SendSignal(ev); return true; } void UIHorizScroll::MouseDown(Event *ev) { UIPoint2D p; int scrollrate = 0; p.x = ev->GetFloat(1); p.y = ev->GetFloat(2); p.x -= m_screenframe.pos.x; p.y -= m_screenframe.pos.y; if (p.x < 0 || p.y < 0) { // out of bounds return; } if (p.x > m_frame.size.width || p.y > m_frame.size.height) { // out of bounds return; } if (m_numitems <= m_pagewidth) { return; } if (p.x < 16.f) { scrollrate = -1; m_pressed = VS_UP_ARROW; } else if (p.x > m_frame.size.width - 16.f) { scrollrate = 1; m_pressed = VS_DOWN_ARROW; } else if (p.x < thumbRect.pos.x) { m_pressed = VS_PAGE_UP; scrollrate = -m_pagewidth; } else if (p.x >= (thumbRect.pos.x + thumbRect.size.width)) { m_pressed = VS_PAGE_DOWN; scrollrate = m_pagewidth; } else { m_pressed = VS_THUMB; m_dragThumbState.itemOffset = m_topitem - getItemFromWidth(p.x); m_dragThumbState.orgItem = m_topitem; uWinMan.setFirstResponder(this); } if (scrollrate) { Event *event = new Event(EV_HScrollbar_Scroll); event->AddInteger(scrollrate); event->AddInteger(0); CancelEventsOfType(EV_HScrollbar_Scroll); PostEvent(event, 0); uWinMan.setFirstResponder(this); } } int UIHorizScroll::getItemFromWidth(float height) { return (int)((height - 16.0) * m_numitems / (m_frame.size.width - 32.0)); } void UIHorizScroll::MouseUp(Event *ev) { CancelEventsOfType(EV_HScrollbar_Scroll); if (uWinMan.getFirstResponder() == this) { uWinMan.setFirstResponder(NULL); } m_pressed = VS_NONE; } void UIHorizScroll::MouseDragged(Event *ev) { UIPoint2D p; if (m_pressed != VS_THUMB) { return; } p.x = ev->GetFloat(1); p.y = ev->GetFloat(2); if (p.y - m_screenframe.pos.y < -24 || m_frame.size.height + 24.0 < p.y - m_screenframe.pos.y) { AttemptScrollTo(m_dragThumbState.orgItem); } else { AttemptScrollTo(m_dragThumbState.itemOffset + getItemFromWidth(p.x - m_screenframe.pos.x)); } } void UIHorizScroll::InitFrameAlignRight(UIWidget *parent) { UIRect2D frame, frameOut; frame = parent->getClientFrame(); frameOut.pos.x = 0; frameOut.pos.y = frame.pos.y + frame.size.height - m_vVirtualScale[0] * 16.f; frameOut.size.width = frame.size.width - m_vVirtualScale[0] * 16.f; frameOut.size.height = m_vVirtualScale[0] * 16.f; if (m_frameinitted) { setFrame(frameOut); return; } InitFrame(parent, frameOut, -1); } void UIHorizScroll::MouseEnter(Event *ev) { uWinMan.ActivateControl(this); } void UIHorizScroll::MouseLeave(Event *ev) {} bool UIHorizScroll::isEnoughItems(void) { return m_numitems > m_pagewidth; } void UIHorizScroll::setNumItems(int i) { m_numitems = i; } void UIHorizScroll::setPageWidth(int i) { m_pagewidth = i; } void UIHorizScroll::setTopItem(int i) { m_topitem = i; } int UIHorizScroll::getTopItem(void) { return m_topitem; } int UIHorizScroll::getPageWidth(void) { return m_pagewidth; } int UIHorizScroll::getNumItems(void) { return m_numitems; } void UIHorizScroll::setThumbColor(const UColor& thumb) { m_thumbcolor = thumb; } void UIHorizScroll::setSolidBorderColor(const UColor& col) { m_solidbordercolor = col; }