/* * Author: Andrew Mann * * Copyright (C) 2004 PlaneShift Team (info@planeshift.it, * http://www.planeshift.it) * * This program 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 (version 2 of the License) * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include "pawsscrollpane.h" #include "partview.h" #include "paws/pawsmanager.h" #include "paws/pawsbutton.h" #include "paws/pawstextbox.h" #include "paws/pawslistbox.h" #include "paws/pawscrollbar.h" #include "paws/pawsborder.h" pawsScrollPane::pawsScrollPane( PawsManager* manager ) :pawsWidget( manager ) { pane_scroll=NULL; depth=0; scroll_visible=false; scroll_vertical=true; scroll_side=SCROLL_ON_RIGHT; mouse_dragging=false; } pawsScrollPane::~pawsScrollPane() { delete pane_scroll; } bool pawsScrollPane::Setup( iDocumentNode* node ) { csRef scrollbarnode,subnode; scrollbarnode = node->GetNode( "scrollbar" ); if ( scrollbarnode ) { // Check for direction csRef directionAttribute = scrollbarnode->GetAttribute("direction"); if ( directionAttribute ) { csString value( directionAttribute->GetValue() ); if ( value.CompareNoCase("horizontal")) scroll_vertical=false; else scroll_vertical=true; } // Check for relative location csRef locationAttribute = scrollbarnode->GetAttribute("location"); if ( locationAttribute ) { csString value( locationAttribute->GetValue() ); if ( value.CompareNoCase("top") || value.CompareNoCase("left") ) scroll_side=SCROLL_ON_LEFT; else scroll_side=SCROLL_ON_RIGHT; } } return true; } bool pawsScrollPane::PostSetup() { int attach; pane_scroll = ( pawsScrollBar* ) windowManager->CreateWidget( "pawsScrollBar" ); pane_scroll->SetParent( this ); if (scroll_vertical) { if (scroll_side==SCROLL_ON_RIGHT) { attach = ATTACH_TOP | ATTACH_BOTTOM | ATTACH_RIGHT; pane_scroll->SetRelativeFrame( defaultFrame.Width() - GetActualWidth(15), GetActualHeight(6), GetActualWidth(15), defaultFrame.Height() - GetActualHeight(12) ); } else { attach = ATTACH_TOP | ATTACH_BOTTOM | ATTACH_LEFT; pane_scroll->SetRelativeFrame( 0, GetActualHeight(6), GetActualWidth(15), defaultFrame.Height() - GetActualHeight(12) ); } pane_scroll->SetHorizontal(false); } else { if (scroll_side==SCROLL_ON_BOTTOM) { attach = ATTACH_LEFT | ATTACH_BOTTOM | ATTACH_RIGHT; pane_scroll->SetRelativeFrame( GetActualWidth(6), defaultFrame.Height() - GetActualHeight(15), defaultFrame.Width() - GetActualWidth(12), GetActualHeight(15) ); } else { attach = ATTACH_LEFT | ATTACH_TOP | ATTACH_RIGHT; pane_scroll->SetRelativeFrame( GetActualWidth(6), 0, defaultFrame.Width() - GetActualWidth(12), GetActualHeight(15) ); } pane_scroll->SetHorizontal(true); } pane_scroll->SetAttachFlags( attach ); pane_scroll->PostSetup(); pane_scroll->SetMaxValue(100.0f); pane_scroll->SetTickValue(10.0f); pane_scroll->SetCurrentValue(0.0f); // Do not start off as a child. If a scrollbar is needed it will be added on the first draw //AddChild(pane_scroll); return true; } void pawsScrollPane::DrawChildren() { int i; if (border) { // Adjust clipRect // This is a bit of a hack. The clipRect in a widget with a border includes the border region // Children should be clipped to a smaller region to avoid overwriting the border if (screenFrame.xmin == clipRect.xmin) clipRect.xmin+=3; if (screenFrame.xmax == clipRect.xmax) clipRect.xmax-=3; if (screenFrame.ymin == clipRect.ymin) clipRect.ymin+=3; if (screenFrame.ymax == clipRect.ymax) clipRect.ymax-=3; } if (mouse_dragging) HandleMouseDrag(); if (scroll_vertical) { int y; // Readjust the position of all children if (border) y=3; else y=0; for (i=0;iIsVisible()) continue; // Don't consider the scrollbar here if (children[i] == pane_scroll) continue; childframe=children[i]->ScreenFrame(); // Calculate the height needed based on the border if present if (children[i]->GetBorder()) childheight=children[i]->GetBorder()->GetRect().Height(); else childheight=childframe.Height(); if (y+childheight > depth && y <(screenFrame.Height()+depth)) { children[i]->SetRelativeFramePos(childframe.xmin-screenFrame.xmin,y-depth); children[i]->Draw(); } y+=childheight; } // Scrollbar is needed if (y > screenFrame.Height()) { int scrollrange=y-screenFrame.Height(); if (scrollrange != pane_scroll->GetMaxValue()) pane_scroll->SetMaxValue(scrollrange); if (depth != pane_scroll->GetCurrentValue()) pane_scroll->SetCurrentValue(depth); if (!scroll_visible) { AddChild(pane_scroll); if (scroll_side==SCROLL_ON_RIGHT) { pane_scroll->SetRelativeFrame( defaultFrame.Width() - GetActualWidth(15), GetActualHeight(6), GetActualWidth(15), defaultFrame.Height() - GetActualHeight(12) ); } else { pane_scroll->SetRelativeFrame( 0, GetActualHeight(6), GetActualWidth(15), defaultFrame.Height() - GetActualHeight(12) ); } scroll_visible=true; } pane_scroll->Draw(); } else { depth=0; if (scroll_visible) { RemoveChild(pane_scroll); scroll_visible=false; } } } else { int x; // Readjust the position of all children if (border) x=3; else x=0; for (i=0;iIsVisible()) continue; // Don't consider the scrollbar here if (children[i] == pane_scroll) continue; childframe=children[i]->ScreenFrame(); // Calculate the width needed based on the border if present if (children[i]->GetBorder()) childwidth=children[i]->GetBorder()->GetRect().Width(); else childwidth=childframe.Width(); if (x+childwidth > depth && x <(screenFrame.Width()+depth)) { children[i]->SetRelativeFramePos(x-depth,childframe.ymin-screenFrame.ymin); children[i]->Draw(); } x+=childwidth; } // Scrollbar is needed if (x > screenFrame.Width()) { int scrollrange=x-screenFrame.Width(); if (scrollrange != pane_scroll->GetMaxValue()) pane_scroll->SetMaxValue(scrollrange); if (depth != pane_scroll->GetCurrentValue()) pane_scroll->SetCurrentValue(depth); if (!scroll_visible) { AddChild(pane_scroll); if (scroll_side==SCROLL_ON_BOTTOM) { pane_scroll->SetRelativeFrame( GetActualWidth(6), defaultFrame.Height() - GetActualHeight(15), defaultFrame.Width() - GetActualWidth(12), GetActualHeight(15) ); } else { pane_scroll->SetRelativeFrame( GetActualWidth(6), 0, defaultFrame.Width() - GetActualWidth(12), GetActualHeight(15) ); } scroll_visible=true; } pane_scroll->Draw(); } else { depth=0; if (scroll_visible) { RemoveChild(pane_scroll); scroll_visible=false; } } } } bool pawsScrollPane::OnScroll( int scrollDirection, pawsScrollBar* widget ) { if (!widget) return false; if (widget == pane_scroll) { depth=widget->GetCurrentValue(); } return true; } void pawsScrollPane::HandleMouseDrag() { csPoint mousePos; int relMouseCoord; // coordinate of mouse cursor relative to the scroll direction of this pane if (!scroll_visible) { mouse_dragging=false; return; } mousePos = windowManager->GetMouse()->GetPosition(); if (scroll_vertical) { if (mousePos.y > screenFrame.ymax) { mouse_dragging=false; mousePos.y=screenFrame.ymax; } if (mousePos.y < screenFrame.ymin) { mouse_dragging=false; mousePos.y=screenFrame.ymin; } relMouseCoord=mousePos.y - mouse_last_position.y; mouse_last_position.Set(mousePos); depth-=relMouseCoord; if (depth<0) depth=0; if (pane_scroll && (depth > pane_scroll->GetMaxValue())) depth = pane_scroll->GetMaxValue(); } else { if (mousePos.x > screenFrame.xmax) { mouse_dragging=false; mousePos.x=screenFrame.xmax; } if (mousePos.x < screenFrame.xmin) { mouse_dragging=false; mousePos.x=screenFrame.xmin; } relMouseCoord=mousePos.x - mouse_last_position.x; mouse_last_position.Set(mousePos); depth-=relMouseCoord; if (depth<0) depth=0; if (pane_scroll && (depth > pane_scroll->GetMaxValue())) depth = pane_scroll->GetMaxValue(); } } bool pawsScrollPane::OnMouseDown( int button, int modifiers, int x, int y ) { // None of the children handled this, so we'll handle it as a drag if (button == 1 && scroll_visible) { mouse_dragging=true; mouse_last_position.Set(x,y); return true; } if (parent) return parent->OnMouseDown(button,modifiers,x,y); return false; } bool pawsScrollPane::OnMouseUp( int button, int modifiers, int x, int y ) { // None of the children handled this, so we'll handle it as a drag if (button == 1 && mouse_dragging) { mouse_dragging=false; return true; } if (parent) return parent->OnMouseUp(button,modifiers,x,y); return false; } void pawsScrollPane::BringToTop( pawsWidget* widget ) { // Do nothing. Do not reorder children. }