Code Search for Developers
 
 
  

Scroll.cpp from FreeOrion at Krugle


Show Scroll.cpp syntax highlighted

/* GG is a GUI for SDL and OpenGL.
   Copyright (C) 2003 T. Zachary Laine

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public License
   as published by the Free Software Foundation; either version 2.1
   of the License, or (at your option) any later version.
   
   This library 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
   Lesser General Public License for more details.
    
   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA

   If you do not wish to comply with the terms of the LGPL please
   contact the author as other terms are available for a fee.
    
   Zach Laine
   whatwasthataddress@hotmail.com */

#include <GG/Scroll.h>

#include <GG/Button.h>
#include <GG/DrawUtil.h>
#include <GG/StyleFactory.h>
#include <GG/WndEditor.h>
#include <GG/WndEvent.h>


using namespace GG;

namespace {
    const int MIN_TAB_SIZE = 5;
}

////////////////////////////////////////////////
// GG::Scroll
////////////////////////////////////////////////
Scroll::Scroll() :
    Control(),
    m_orientation(VERTICAL),
    m_posn(0),
    m_range_min(0),
    m_range_max(99),
    m_line_sz(5),
    m_page_sz(25),
    m_tab(0),
    m_incr(0),
    m_decr(0),
    m_initial_depressed_region(SBR_NONE),
    m_depressed_region(SBR_NONE)
{}

Scroll::Scroll(int x, int y, int w, int h, Orientation orientation, Clr color, Clr interior, Flags<WndFlag> flags/* = CLICKABLE | REPEAT_BUTTON_DOWN*/) :
    Control(x, y, w, h, flags),
    m_int_color(interior),
    m_orientation(orientation),
    m_posn(0),
    m_range_min(0),
    m_range_max(99),
    m_line_sz(5),
    m_page_sz(25),
    m_tab(0),
    m_incr(0),
    m_decr(0),
    m_initial_depressed_region(SBR_NONE),
    m_depressed_region(SBR_NONE)
{
    Control::SetColor(color);
    boost::shared_ptr<Font> null_font;
    boost::shared_ptr<StyleFactory> style = GetStyleFactory();
    if (m_orientation == VERTICAL) {
        m_decr = style->NewScrollUpButton(   0,     0, w, w,          "", null_font, color);
        m_incr = style->NewScrollDownButton( 0, h - w, w, w,          "", null_font, color);
        m_tab  = style->NewVScrollTabButton( 0,     w, w, TabWidth(), "", null_font, color);
    } else {
        m_decr = style->NewScrollLeftButton( 0,     0, h,          h, "", null_font, color);
        m_incr = style->NewScrollRightButton(w - h, 0, h,          h, "", null_font, color);
        m_tab  = style->NewHScrollTabButton( h,     0, TabWidth(), h, "", null_font, color);
    }
    AttachChild(m_decr);
    AttachChild(m_incr);
    AttachChild(m_tab);
    Connect(m_decr->ClickedSignal, &Scroll::ScrollLineDecr, this);
    Connect(m_incr->ClickedSignal, &Scroll::ScrollLineIncr, this);
    m_tab->InstallEventFilter(this);
}

Pt Scroll::MinUsableSize() const
{
    Pt retval;
    const int MIN_DRAGABLE_SIZE = 2;
    if (m_orientation == VERTICAL) {
        retval.x = MIN_DRAGABLE_SIZE;
        int decr_y = m_decr->MinUsableSize().y;
        int incr_y = m_incr->MinUsableSize().y;
        retval.y = decr_y + incr_y + 3 * std::min(decr_y, incr_y);
    } else {
        int decr_x = m_decr->MinUsableSize().x;
        int incr_x = m_incr->MinUsableSize().x;
        retval.x = decr_x + incr_x + 3 * std::min(decr_x, incr_x);
        retval.y = MIN_DRAGABLE_SIZE;
    }
    return retval;
}

std::pair<int, int> Scroll::PosnRange() const
{
    return std::pair<int, int>(m_posn, m_posn + m_page_sz);
}

std::pair<int, int> Scroll::ScrollRange() const
{
    return std::pair<int, int>(m_range_min, m_range_max);
}

int Scroll::LineSize() const
{
    return m_line_sz;
}

int Scroll::PageSize() const
{
    return m_page_sz;
}
    
Clr Scroll::InteriorColor() const
{
    return m_int_color;
}

Orientation Scroll::ScrollOrientation() const
{
    return m_orientation;
}

void Scroll::Render()
{
    Pt ul = UpperLeft(), lr = LowerRight();
    Clr int_color_to_use = Disabled() ? DisabledColor(m_int_color) : m_int_color;
    FlatRectangle(ul.x, ul.y, lr.x, lr.y, int_color_to_use, CLR_ZERO, 0);
}

void Scroll::LButtonDown(const Pt& pt, Flags<ModKey> mod_keys)
{
    if (!Disabled()) {
        // when a button is pressed, record the region of the control the cursor is over
        ScrollRegion region = RegionUnder(pt);
        if (m_initial_depressed_region == SBR_NONE)
            m_initial_depressed_region = region;
        m_depressed_region = region;
        if (m_depressed_region == m_initial_depressed_region) {
            switch (m_depressed_region)
            {
            case SBR_PAGE_DN:
                ScrollPageDecr();
                break;
            case SBR_PAGE_UP:
                ScrollPageIncr();
                break;
            default: break;
            }
        }
    }
}

void Scroll::LButtonUp(const Pt& pt, Flags<ModKey> mod_keys)
{
    if (!Disabled()) {
        m_decr->SetState(Button::BN_UNPRESSED);
        m_incr->SetState(Button::BN_UNPRESSED);
        m_initial_depressed_region = SBR_NONE;
        m_depressed_region = SBR_NONE;
    }
}

void Scroll::LClick(const Pt& pt, Flags<ModKey> mod_keys)
{
    LButtonUp(pt, mod_keys);
}

void Scroll::MouseHere(const Pt& pt, Flags<ModKey> mod_keys)
{
    LButtonUp(pt, mod_keys);
}

void Scroll::SizeMove(const Pt& ul, const Pt& lr)
{
    Wnd::SizeMove(ul, lr);
    int bn_width = (m_orientation == VERTICAL) ? Size().x : Size().y;
    m_decr->SizeMove(Pt(0, 0), Pt(bn_width, bn_width));
    m_incr->SizeMove(Size() - Pt(bn_width, bn_width), Size());
    m_tab->SizeMove(m_tab->RelativeUpperLeft(), (m_orientation == VERTICAL) ? Pt(bn_width, m_tab->RelativeLowerRight().y) :
                    Pt(m_tab->RelativeLowerRight().x, bn_width));
    SizeScroll(m_range_min, m_range_max, m_line_sz, m_page_sz); // update tab size and position
}

void Scroll::Disable(bool b/* = true*/)
{
    Control::Disable(b);
    m_tab->Disable(b);
    m_incr->Disable(b);
    m_decr->Disable(b);
}

void Scroll::SetColor(Clr c)
{
    Control::SetColor(c);
    m_tab->SetColor(c);
    m_incr->SetColor(c);
    m_decr->SetColor(c);
}

void Scroll::SetInteriorColor(Clr c)
{
    m_int_color = c;
}

void Scroll::SizeScroll(int min, int max, int line, int page)
{
    m_line_sz = line;
    m_range_min = std::min(min, max);
    m_range_max = std::max(min, max);
    int old_posn = m_posn;
    m_page_sz = page;
    if (m_page_sz > (m_range_max - m_range_min + 1)) m_page_sz = (m_range_max - m_range_min + 1);
    if (m_posn > m_range_max - (m_page_sz - 1)) m_posn = m_range_max - (m_page_sz - 1);
    if (m_posn < m_range_min) m_posn = m_range_min;
    Pt tab_ul = m_tab->RelativeUpperLeft();
    Pt tab_lr = m_orientation == VERTICAL ? Pt(m_tab->RelativeLowerRight().x, tab_ul.y + TabWidth()):
    Pt(tab_ul.x + TabWidth(), m_tab->RelativeLowerRight().y);
    m_tab->SizeMove(tab_ul, tab_lr);
    MoveTabToPosn();
    if (old_posn != m_posn) {
        ScrolledSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
        ScrolledAndStoppedSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
    }
}

void Scroll::SetMax(int max)        
{
    SizeScroll(m_range_min, max, m_line_sz, m_page_sz);
}

void Scroll::SetMin(int min)        
{
    SizeScroll(min, m_range_max, m_line_sz, m_page_sz);
}

void Scroll::SetLineSize(int line)
{
    SizeScroll(m_range_min, m_range_max, line, m_page_sz);
}

void Scroll::SetPageSize(int page)  
{
    SizeScroll(m_range_min, m_range_max, m_line_sz, page);
}

void Scroll::ScrollTo(int p)
{
    int old_posn = m_posn;
    if (p < m_range_min)
        m_posn = m_range_min;
    else if (p > m_range_max - m_page_sz)
        m_posn = m_range_max - m_page_sz;
    else
        m_posn = p;
    MoveTabToPosn();
    if (old_posn != m_posn) {
        ScrolledSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
        ScrolledAndStoppedSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
    }
}

void Scroll::ScrollLineIncr()
{
    int old_posn = m_posn;
    if (m_posn + m_line_sz <= m_range_max - m_page_sz)
        m_posn += m_line_sz;
    else
        m_posn = m_range_max - (m_page_sz - 1);
    MoveTabToPosn();
    if (old_posn != m_posn) {
        ScrolledSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
        ScrolledAndStoppedSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
    }
}

void Scroll::ScrollLineDecr()
{
    int old_posn = m_posn;
    if (m_posn - m_line_sz >= m_range_min)
        m_posn -= m_line_sz;
    else
        m_posn = m_range_min;
    MoveTabToPosn();
    if (old_posn != m_posn) {
        ScrolledSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
        ScrolledAndStoppedSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
    }
}

void Scroll::ScrollPageIncr()
{
    int old_posn = m_posn;
    if (m_posn + m_page_sz <= m_range_max - m_page_sz)
        m_posn += m_page_sz;
    else
        m_posn = m_range_max - (m_page_sz - 1);
    MoveTabToPosn();
    if (old_posn != m_posn) {
        ScrolledSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
        ScrolledAndStoppedSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
    }
}

void Scroll::ScrollPageDecr()
{
    int old_posn = m_posn;
    if (m_posn - m_page_sz >= m_range_min)
        m_posn -= m_page_sz;
    else
        m_posn = m_range_min;
    MoveTabToPosn();
    if (old_posn != m_posn) {
        ScrolledSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
        ScrolledAndStoppedSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
    }
}

void Scroll::DefineAttributes(WndEditor* editor)
{
    if (!editor)
        return;
    Control::DefineAttributes(editor);
    editor->Label("Scroll");
    editor->Attribute("Interior Color", m_int_color);
    editor->Attribute("Range Min", m_range_min);
    editor->Attribute("Range Max", m_range_max);
    editor->Attribute("Line Size", m_line_sz);
    editor->Attribute("Page Size", m_page_sz);
}

int Scroll::TabSpace() const
{
    // tab_space is the space the tab has to move about in (the control's width less the width of the incr & decr buttons)
    return (m_orientation == VERTICAL ?
            Size().y - m_incr->Size().y - m_decr->Size().y :
            Size().x - m_incr->Size().x - m_decr->Size().x);
}

int Scroll::TabWidth() const
{
    return std::max(TabSpace() * m_page_sz / (m_range_max - m_range_min + 1), MIN_TAB_SIZE);
}

Scroll::ScrollRegion Scroll::RegionUnder(const Pt& pt)
{
    ScrollRegion retval;
    Pt ul = ClientUpperLeft();
    if (pt.x - ul.x < m_tab->RelativeUpperLeft().x || pt.y - ul.y <= m_tab->RelativeUpperLeft().y)
        retval = SBR_PAGE_DN;
    else
        retval = SBR_PAGE_UP;
    return retval;
}

Button* Scroll::TabButton() const
{
    return m_tab;
}

Button* Scroll::IncrButton() const
{
    return m_incr;
}

Button* Scroll::DecrButton() const
{
    return m_decr;
}

bool Scroll::EventFilter(Wnd* w, const WndEvent& event)
{
    if (w == m_tab) {
        switch (event.Type()) {
        case WndEvent::LDrag: {
            if (!Disabled()) {
                Pt new_ul = m_tab->RelativeUpperLeft() + event.DragMove();
                if (m_orientation == VERTICAL) {
                    new_ul.x = m_tab->RelativeUpperLeft().x;
                    new_ul.y = std::max(0 + m_decr->Height(),
                                        std::min(new_ul.y, ClientHeight() - m_incr->Height() - m_tab->Height()));
                } else {
                    new_ul.x = std::max(0 + m_decr->Width(),
                                        std::min(new_ul.x, ClientWidth() - m_incr->Width() - m_tab->Width()));
                    new_ul.y = m_tab->RelativeUpperLeft().y;
                }
                m_tab->MoveTo(new_ul);
                UpdatePosn();
            }
            return true;
        }
        default:
            break;
        }
    }
    return false;
}

void Scroll::UpdatePosn()
{
    int old_posn = m_posn;
    int before_tab = (m_orientation == VERTICAL ?   // the tabspace before the tab's lower-value side
                      m_tab->RelativeUpperLeft().y - m_decr->Size().y :
                      m_tab->RelativeUpperLeft().x - m_decr->Size().x );
    int tab_space = TabSpace();
    m_posn = static_cast<int>(m_range_min + static_cast<double>(before_tab) / tab_space * (m_range_max - m_range_min + 1) + 0.5);
    m_posn = std::min(m_range_max - m_page_sz + 1, std::max(m_range_min, m_posn));
    if (old_posn != m_posn)
        ScrolledSignal(m_posn, m_posn + m_page_sz, m_range_min, m_range_max);
}

void Scroll::MoveTabToPosn()
{
    int start_tabspace = (m_orientation==VERTICAL ?      // what is the tab's lowest posible extent?
                          m_decr->Size().y :
                          m_decr->Size().x);
    int end_tabspace = (m_orientation==VERTICAL ?      // what is its highest?
                        Size().y - m_incr->Size().y :
                        Size().x - m_incr->Size().x);

    m_tab->MoveTo(m_orientation==VERTICAL ?
                  Pt(m_tab->RelativeUpperLeft().x,
                     static_cast<int>((static_cast<double>(m_posn - m_range_min) / (m_range_max - m_range_min + 1)) * (end_tabspace - start_tabspace + 1) + start_tabspace)) :
                  Pt(static_cast<int>((static_cast<double>(m_posn - m_range_min) / (m_range_max - m_range_min + 1)) * (end_tabspace - start_tabspace + 1) + start_tabspace),
                     m_tab->RelativeUpperLeft().y));
}




See more files for this project here

FreeOrion

FreeOrion brings nation building to a galactic scale with its full-featured grand campaign and in-game racial histories, in addition to the classic 4X model of galactic conquest and tactical combat.

Project homepage: http://sourceforge.net/projects/freeorion
Programming language(s): C,C++
License: other

  Ogre/
    Plugins/
      OISInput.cfg
      OISInput.cpp
      OISInput.h
      OgreGUIInputPlugin.cpp
      OgreGUIInputPlugin.h
      SConscript
    OgreGUI.cpp
    SConscript
  SDL/
    SConscript
    SDLGUI.cpp
  dialogs/
    ColorDlg.cpp
    FileDlg.cpp
    SConscript
    ThreeButtonDlg.cpp
  AlignmentFlags.cpp
  Base.cpp
  BrowseInfoWnd.cpp
  Button.cpp
  Clr.cpp
  Control.cpp
  Cursor.cpp
  DrawUtil.cpp
  DropDownList.cpp
  DynamicGraphic.cpp
  Edit.cpp
  EventPump.cpp
  Font.cpp
  GUI.cpp
  Layout.cpp
  ListBox.cpp
  Menu.cpp
  MultiEdit.cpp
  Plugin.cpp
  PluginInterface.cpp
  PtRect.cpp
  SConscript
  Scroll.cpp
  Slider.cpp
  StaticGraphic.cpp
  StyleFactory.cpp
  TabWnd.cpp
  TextControl.cpp
  Texture.cpp
  Timer.cpp
  Wnd.cpp
  WndEditor.cpp
  WndEvent.cpp
  ZList.cpp
  _vsnprintf.c