Guichan library and few examples, by Lubomyr

This commit is contained in:
Sergii Pylypenko
2013-11-26 20:46:06 +02:00
parent aa83519892
commit 0017de045f
133 changed files with 28296 additions and 0 deletions

View File

@@ -0,0 +1,284 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/button.hpp"
#include "guichan/exception.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/mouseevent.hpp"
#include "guichan/mouseinput.hpp"
namespace gcn
{
Button::Button()
: mHasMouse(false),
mKeyPressed(false),
mMousePressed(false),
mAlignment(Graphics::CENTER),
mSpacing(4)
{
setFocusable(true);
adjustSize();
setFrameSize(1);
addMouseListener(this);
addKeyListener(this);
addFocusListener(this);
}
Button::Button(const std::string& caption)
: mCaption(caption),
mHasMouse(false),
mKeyPressed(false),
mMousePressed(false),
mAlignment(Graphics::CENTER),
mSpacing(4)
{
setFocusable(true);
adjustSize();
setFrameSize(1);
addMouseListener(this);
addKeyListener(this);
addFocusListener(this);
}
void Button::setCaption(const std::string& caption)
{
mCaption = caption;
}
const std::string& Button::getCaption() const
{
return mCaption;
}
void Button::setAlignment(Graphics::Alignment alignment)
{
mAlignment = alignment;
}
Graphics::Alignment Button::getAlignment() const
{
return mAlignment;
}
void Button::setSpacing(unsigned int spacing)
{
mSpacing = spacing;
}
unsigned int Button::getSpacing() const
{
return mSpacing;
}
void Button::draw(Graphics* graphics)
{
Color faceColor = getBaseColor();
Color highlightColor, shadowColor;
int alpha = getBaseColor().a;
if (isPressed())
{
faceColor = faceColor - 0x303030;
faceColor.a = alpha;
highlightColor = faceColor - 0x303030;
highlightColor.a = alpha;
shadowColor = faceColor + 0x303030;
shadowColor.a = alpha;
}
else
{
highlightColor = faceColor + 0x303030;
highlightColor.a = alpha;
shadowColor = faceColor - 0x303030;
shadowColor.a = alpha;
}
graphics->setColor(faceColor);
graphics->fillRectangle(Rectangle(1, 1, getDimension().width-1, getHeight() - 1));
graphics->setColor(highlightColor);
graphics->drawLine(0, 0, getWidth() - 1, 0);
graphics->drawLine(0, 1, 0, getHeight() - 1);
graphics->setColor(shadowColor);
graphics->drawLine(getWidth() - 1, 1, getWidth() - 1, getHeight() - 1);
graphics->drawLine(1, getHeight() - 1, getWidth() - 1, getHeight() - 1);
graphics->setColor(getForegroundColor());
int textX;
int textY = getHeight() / 2 - getFont()->getHeight() / 2;
switch (getAlignment())
{
case Graphics::LEFT:
textX = mSpacing;
break;
case Graphics::CENTER:
textX = getWidth() / 2;
break;
case Graphics::RIGHT:
textX = getWidth() - mSpacing;
break;
default:
throw GCN_EXCEPTION("Unknown alignment.");
}
graphics->setFont(getFont());
if (isPressed())
{
graphics->drawText(getCaption(), textX + 1, textY + 1, getAlignment());
}
else
{
graphics->drawText(getCaption(), textX, textY, getAlignment());
if (isFocused())
{
graphics->drawRectangle(Rectangle(2, 2, getWidth() - 4,
getHeight() - 4));
}
}
}
void Button::adjustSize()
{
setWidth(getFont()->getWidth(mCaption) + 2*mSpacing);
setHeight(getFont()->getHeight() + 2*mSpacing);
}
bool Button::isPressed() const
{
if (mMousePressed)
{
return mHasMouse;
}
else
{
return mKeyPressed;
}
}
void Button::mousePressed(MouseEvent& mouseEvent)
{
if (mouseEvent.getButton() == MouseEvent::LEFT)
{
mMousePressed = true;
mouseEvent.consume();
}
}
void Button::mouseExited(MouseEvent& mouseEvent)
{
mHasMouse = false;
}
void Button::mouseEntered(MouseEvent& mouseEvent)
{
mHasMouse = true;
}
void Button::mouseReleased(MouseEvent& mouseEvent)
{
if (mouseEvent.getButton() == MouseEvent::LEFT
&& mMousePressed
&& mHasMouse)
{
mMousePressed = false;
distributeActionEvent();
mouseEvent.consume();
}
else if (mouseEvent.getButton() == MouseEvent::LEFT)
{
mMousePressed = false;
mouseEvent.consume();
}
}
void Button::mouseDragged(MouseEvent& mouseEvent)
{
mouseEvent.consume();
}
void Button::keyPressed(KeyEvent& keyEvent)
{
Key key = keyEvent.getKey();
if (key.getValue() == Key::ENTER
|| key.getValue() == Key::SPACE)
{
mKeyPressed = true;
keyEvent.consume();
}
}
void Button::keyReleased(KeyEvent& keyEvent)
{
Key key = keyEvent.getKey();
if ((key.getValue() == Key::ENTER
|| key.getValue() == Key::SPACE)
&& mKeyPressed)
{
mKeyPressed = false;
distributeActionEvent();
keyEvent.consume();
}
}
void Button::focusLost(const Event& event)
{
mMousePressed = false;
mKeyPressed = false;
}
}

View File

@@ -0,0 +1,189 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/checkbox.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/mouseinput.hpp"
namespace gcn
{
CheckBox::CheckBox()
{
setSelected(false);
setFocusable(true);
addMouseListener(this);
addKeyListener(this);
}
CheckBox::CheckBox(const std::string &caption, bool selected)
{
setCaption(caption);
setSelected(selected);
setFocusable(true);
addMouseListener(this);
addKeyListener(this);
adjustSize();
}
void CheckBox::draw(Graphics* graphics)
{
drawBox(graphics);
graphics->setFont(getFont());
graphics->setColor(getForegroundColor());
const int h = getHeight() + getHeight() / 2;
graphics->drawText(getCaption(), h - 2, 0);
}
void CheckBox::drawBox(Graphics *graphics)
{
const int h = getHeight() - 2;
const int alpha = getBaseColor().a;
Color faceColor = getBaseColor();
faceColor.a = alpha;
Color highlightColor = faceColor + 0x303030;
highlightColor.a = alpha;
Color shadowColor = faceColor - 0x303030;
shadowColor.a = alpha;
graphics->setColor(shadowColor);
graphics->drawLine(1, 1, h, 1);
graphics->drawLine(1, 1, 1, h);
graphics->setColor(highlightColor);
graphics->drawLine(h, 1, h, h);
graphics->drawLine(1, h, h - 1, h);
graphics->setColor(getBackgroundColor());
graphics->fillRectangle(Rectangle(2, 2, h - 2, h - 2));
graphics->setColor(getForegroundColor());
if (isFocused())
{
graphics->drawRectangle(Rectangle(0, 0, h + 2, h + 2));
}
if (mSelected)
{
graphics->drawLine(3, 5, 3, h - 2);
graphics->drawLine(4, 5, 4, h - 2);
graphics->drawLine(5, h - 3, h - 2, 4);
graphics->drawLine(5, h - 4, h - 4, 5);
}
}
bool CheckBox::isSelected() const
{
return mSelected;
}
void CheckBox::setSelected(bool selected)
{
mSelected = selected;
}
const std::string &CheckBox::getCaption() const
{
return mCaption;
}
void CheckBox::setCaption(const std::string& caption)
{
mCaption = caption;
}
void CheckBox::keyPressed(KeyEvent& keyEvent)
{
Key key = keyEvent.getKey();
if (key.getValue() == Key::ENTER ||
key.getValue() == Key::SPACE)
{
toggleSelected();
keyEvent.consume();
}
}
void CheckBox::mouseClicked(MouseEvent& mouseEvent)
{
if (mouseEvent.getButton() == MouseEvent::LEFT)
{
toggleSelected();
}
}
void CheckBox::mouseDragged(MouseEvent& mouseEvent)
{
mouseEvent.consume();
}
void CheckBox::adjustSize()
{
int height = getFont()->getHeight();
setHeight(height);
setWidth(getFont()->getWidth(mCaption) + height + height / 2);
}
void CheckBox::toggleSelected()
{
mSelected = !mSelected;
distributeActionEvent();
}
}

View File

@@ -0,0 +1,112 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/container.hpp"
#include "guichan/exception.hpp"
#include "guichan/graphics.hpp"
namespace gcn
{
Container::Container()
{
mOpaque = true;
}
Container::~Container()
{
}
void Container::draw(Graphics* graphics)
{
if (isOpaque())
{
graphics->setColor(getBaseColor());
graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));
}
drawChildren(graphics);
}
void Container::setOpaque(bool opaque)
{
mOpaque = opaque;
}
bool Container::isOpaque() const
{
return mOpaque;
}
void Container::add(Widget* widget)
{
BasicContainer::add(widget);
}
void Container::add(Widget* widget, int x, int y)
{
widget->setPosition(x, y);
BasicContainer::add(widget);
}
void Container::remove(Widget* widget)
{
BasicContainer::remove(widget);
}
void Container::clear()
{
BasicContainer::clear();
}
Widget* Container::findWidgetById(const std::string &id)
{
return BasicContainer::findWidgetById(id);
}
}

View File

@@ -0,0 +1,635 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "guichan/widgets/dropdown.hpp"
#include "guichan/exception.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/listmodel.hpp"
#include "guichan/mouseinput.hpp"
#include "guichan/widgets/listbox.hpp"
#include "guichan/widgets/scrollarea.hpp"
namespace gcn
{
DropDown::DropDown(ListModel *listModel,
ScrollArea *scrollArea,
ListBox *listBox)
{
setWidth(100);
setFocusable(true);
mDroppedDown = false;
mPushed = false;
mIsDragged = false;
setInternalFocusHandler(&mInternalFocusHandler);
mInternalScrollArea = (scrollArea == NULL);
mInternalListBox = (listBox == NULL);
if (mInternalScrollArea)
{
mScrollArea = new ScrollArea();
}
else
{
mScrollArea = scrollArea;
}
if (mInternalListBox)
{
mListBox = new ListBox();
}
else
{
mListBox = listBox;
}
mScrollArea->setContent(mListBox);
add(mScrollArea);
mListBox->addActionListener(this);
mListBox->addSelectionListener(this);
setListModel(listModel);
if (mListBox->getSelected() < 0)
{
mListBox->setSelected(0);
}
addMouseListener(this);
addKeyListener(this);
addFocusListener(this);
adjustHeight();
}
DropDown::~DropDown()
{
if (widgetExists(mListBox))
{
mListBox->removeActionListener(this);
mListBox->removeSelectionListener(this);
}
if (mInternalScrollArea)
{
delete mScrollArea;
}
if (mInternalListBox)
{
delete mListBox;
}
setInternalFocusHandler(NULL);
}
void DropDown::draw(Graphics* graphics)
{
int h;
if (mDroppedDown)
{
h = mFoldedUpHeight;
}
else
{
h = getHeight();
}
Color faceColor = getBaseColor();
Color highlightColor, shadowColor;
int alpha = getBaseColor().a;
highlightColor = faceColor + 0x303030;
highlightColor.a = alpha;
shadowColor = faceColor - 0x303030;
shadowColor.a = alpha;
// Draw a border.
graphics->setColor(shadowColor);
graphics->drawLine(0, 0, getWidth() - 1, 0);
graphics->drawLine(0, 1, 0, h - 2);
graphics->setColor(highlightColor);
graphics->drawLine(getWidth() - 1, 1, getWidth() - 1, h - 1);
graphics->drawLine(0, h - 1, getWidth() - 1, h - 1);
// Push a clip area so the other drawings don't need to worry
// about the border.
graphics->pushClipArea(Rectangle(1, 1, getWidth() - 2, h - 2));
const Rectangle currentClipArea = graphics->getCurrentClipArea();
graphics->setColor(getBackgroundColor());
graphics->fillRectangle(Rectangle(0, 0, currentClipArea.width, currentClipArea.height));
if (isFocused())
{
graphics->setColor(getSelectionColor());
graphics->fillRectangle(Rectangle(0,
0,
currentClipArea.width - currentClipArea.height,
currentClipArea.height));
graphics->setColor(getForegroundColor());
}
if (mListBox->getListModel()
&& mListBox->getSelected() >= 0)
{
graphics->setColor(getForegroundColor());
graphics->setFont(getFont());
graphics->drawText(mListBox->getListModel()->getElementAt(mListBox->getSelected()), 1, 0);
}
// Push a clip area before drawing the button.
graphics->pushClipArea(Rectangle(currentClipArea.width - currentClipArea.height,
0,
currentClipArea.height,
currentClipArea.height));
drawButton(graphics);
graphics->popClipArea();
graphics->popClipArea();
if (mDroppedDown)
{
// Draw a border around the children.
graphics->setColor(shadowColor);
graphics->drawRectangle(Rectangle(0,
mFoldedUpHeight,
getWidth(),
getHeight() - mFoldedUpHeight));
drawChildren(graphics);
}
}
void DropDown::drawButton(Graphics *graphics)
{
Color faceColor, highlightColor, shadowColor;
int offset;
int alpha = getBaseColor().a;
if (mPushed)
{
faceColor = getBaseColor() - 0x303030;
faceColor.a = alpha;
highlightColor = faceColor - 0x303030;
highlightColor.a = alpha;
shadowColor = faceColor + 0x303030;
shadowColor.a = alpha;
offset = 1;
}
else
{
faceColor = getBaseColor();
faceColor.a = alpha;
highlightColor = faceColor + 0x303030;
highlightColor.a = alpha;
shadowColor = faceColor - 0x303030;
shadowColor.a = alpha;
offset = 0;
}
const Rectangle currentClipArea = graphics->getCurrentClipArea();
graphics->setColor(highlightColor);
graphics->drawLine(0,
0,
currentClipArea.width - 1,
0);
graphics->drawLine(0,
1,
0,
currentClipArea.height - 1);
graphics->setColor(shadowColor);
graphics->drawLine(currentClipArea.width - 1,
1,
currentClipArea.width - 1,
currentClipArea.height - 1);
graphics->drawLine(1,
currentClipArea.height - 1,
currentClipArea.width - 2,
currentClipArea.height - 1);
graphics->setColor(faceColor);
graphics->fillRectangle(Rectangle(1,
1,
currentClipArea.width - 2,
currentClipArea.height - 2));
graphics->setColor(getForegroundColor());
int i;
int n = currentClipArea.height / 3;
int dx = currentClipArea.height / 2;
int dy = (currentClipArea.height * 2) / 3;
for (i = 0; i < n; i++)
{
graphics->drawLine(dx - i + offset,
dy - i + offset,
dx + i + offset,
dy - i + offset);
}
}
int DropDown::getSelected() const
{
return mListBox->getSelected();
}
void DropDown::setSelected(int selected)
{
if (selected >= 0)
{
mListBox->setSelected(selected);
}
}
void DropDown::keyPressed(KeyEvent& keyEvent)
{
if (keyEvent.isConsumed())
return;
Key key = keyEvent.getKey();
if ((key.getValue() == Key::ENTER || key.getValue() == Key::SPACE)
&& !mDroppedDown)
{
dropDown();
keyEvent.consume();
}
else if (key.getValue() == Key::UP)
{
setSelected(getSelected() - 1);
keyEvent.consume();
}
else if (key.getValue() == Key::DOWN)
{
setSelected(getSelected() + 1);
keyEvent.consume();
}
}
void DropDown::mousePressed(MouseEvent& mouseEvent)
{
// If we have a mouse press on the widget.
if (0 <= mouseEvent.getY()
&& mouseEvent.getY() < getHeight()
&& mouseEvent.getX() >= 0
&& mouseEvent.getX() < getWidth()
&& mouseEvent.getButton() == MouseEvent::LEFT
&& !mDroppedDown
&& mouseEvent.getSource() == this)
{
mPushed = true;
dropDown();
requestModalMouseInputFocus();
}
// Fold up the listbox if the upper part is clicked after fold down
else if (0 <= mouseEvent.getY()
&& mouseEvent.getY() < mFoldedUpHeight
&& mouseEvent.getX() >= 0
&& mouseEvent.getX() < getWidth()
&& mouseEvent.getButton() == MouseEvent::LEFT
&& mDroppedDown
&& mouseEvent.getSource() == this)
{
mPushed = false;
foldUp();
releaseModalMouseInputFocus();
}
// If we have a mouse press outside the widget
else if (0 > mouseEvent.getY()
|| mouseEvent.getY() >= getHeight()
|| mouseEvent.getX() < 0
|| mouseEvent.getX() >= getWidth())
{
mPushed = false;
foldUp();
}
}
void DropDown::mouseReleased(MouseEvent& mouseEvent)
{
if (mIsDragged)
{
mPushed = false;
}
// Released outside of widget. Can happen when we have modal input focus.
if ((0 > mouseEvent.getY()
|| mouseEvent.getY() >= getHeight()
|| mouseEvent.getX() < 0
|| mouseEvent.getX() >= getWidth())
&& mouseEvent.getButton() == MouseEvent::LEFT
&& isModalMouseInputFocused())
{
releaseModalMouseInputFocus();
if (mIsDragged)
{
foldUp();
}
}
else if (mouseEvent.getButton() == MouseEvent::LEFT)
{
mPushed = false;
}
mIsDragged = false;
}
void DropDown::mouseDragged(MouseEvent& mouseEvent)
{
mIsDragged = true;
mouseEvent.consume();
}
void DropDown::setListModel(ListModel *listModel)
{
mListBox->setListModel(listModel);
if (mListBox->getSelected() < 0)
{
mListBox->setSelected(0);
}
adjustHeight();
}
ListModel *DropDown::getListModel()
{
return mListBox->getListModel();
}
void DropDown::adjustHeight()
{
if (mScrollArea == NULL)
{
throw GCN_EXCEPTION("Scroll area has been deleted.");
}
if (mListBox == NULL)
{
throw GCN_EXCEPTION("List box has been deleted.");
}
int listBoxHeight = mListBox->getHeight();
// We add 2 for the border
int h2 = getFont()->getHeight() + 2;
setHeight(h2);
// The addition/subtraction of 2 compensates for the seperation lines
// seperating the selected element view and the scroll area.
if (mDroppedDown && getParent())
{
int h = getParent()->getChildrenArea().height - getY();
if (listBoxHeight > h - h2 - 2)
{
mScrollArea->setHeight(h - h2 - 2);
setHeight(h);
}
else
{
setHeight(listBoxHeight + h2 + 2);
mScrollArea->setHeight(listBoxHeight);
}
}
mScrollArea->setWidth(getWidth());
// Resize the ListBox to exactly fit the ScrollArea.
mListBox->setWidth(mScrollArea->getChildrenArea().width);
mScrollArea->setPosition(0, 0);
}
void DropDown::dropDown()
{
if (!mDroppedDown)
{
mDroppedDown = true;
mFoldedUpHeight = getHeight();
adjustHeight();
if (getParent())
{
getParent()->moveToTop(this);
}
}
mListBox->requestFocus();
}
void DropDown::foldUp()
{
if (mDroppedDown)
{
mDroppedDown = false;
adjustHeight();
mInternalFocusHandler.focusNone();
}
}
void DropDown::focusLost(const Event& event)
{
foldUp();
mInternalFocusHandler.focusNone();
}
void DropDown::death(const Event& event)
{
if (event.getSource() == mScrollArea)
{
mScrollArea = NULL;
}
BasicContainer::death(event);
}
void DropDown::action(const ActionEvent& actionEvent)
{
foldUp();
releaseModalMouseInputFocus();
distributeActionEvent();
}
Rectangle DropDown::getChildrenArea()
{
if (mDroppedDown)
{
// Calculate the children area (with the one pixel border in mind)
return Rectangle(1,
mFoldedUpHeight + 1,
getWidth() - 2,
getHeight() - mFoldedUpHeight - 2);
}
return Rectangle();
}
void DropDown::setBaseColor(const Color& color)
{
if (mInternalScrollArea)
{
mScrollArea->setBaseColor(color);
}
if (mInternalListBox)
{
mListBox->setBaseColor(color);
}
Widget::setBaseColor(color);
}
void DropDown::setBackgroundColor(const Color& color)
{
if (mInternalScrollArea)
{
mScrollArea->setBackgroundColor(color);
}
if (mInternalListBox)
{
mListBox->setBackgroundColor(color);
}
Widget::setBackgroundColor(color);
}
void DropDown::setForegroundColor(const Color& color)
{
if (mInternalScrollArea)
{
mScrollArea->setForegroundColor(color);
}
if (mInternalListBox)
{
mListBox->setForegroundColor(color);
}
Widget::setForegroundColor(color);
}
void DropDown::setFont(Font *font)
{
if (mInternalScrollArea)
{
mScrollArea->setFont(font);
}
if (mInternalListBox)
{
mListBox->setFont(font);
}
Widget::setFont(font);
}
void DropDown::mouseWheelMovedUp(MouseEvent& mouseEvent)
{
if (isFocused() && mouseEvent.getSource() == this)
{
mouseEvent.consume();
if (mListBox->getSelected() > 0)
{
mListBox->setSelected(mListBox->getSelected() - 1);
}
}
}
void DropDown::mouseWheelMovedDown(MouseEvent& mouseEvent)
{
if (isFocused() && mouseEvent.getSource() == this)
{
mouseEvent.consume();
mListBox->setSelected(mListBox->getSelected() + 1);
}
}
void DropDown::setSelectionColor(const Color& color)
{
Widget::setSelectionColor(color);
if (mInternalListBox)
{
mListBox->setSelectionColor(color);
}
}
void DropDown::valueChanged(const SelectionEvent& event)
{
distributeValueChangedEvent();
}
void DropDown::addSelectionListener(SelectionListener* selectionListener)
{
mSelectionListeners.push_back(selectionListener);
}
void DropDown::removeSelectionListener(SelectionListener* selectionListener)
{
mSelectionListeners.remove(selectionListener);
}
void DropDown::distributeValueChangedEvent()
{
SelectionListenerIterator iter;
for (iter = mSelectionListeners.begin(); iter != mSelectionListeners.end(); ++iter)
{
SelectionEvent event(this);
(*iter)->valueChanged(event);
}
}
}

View File

@@ -0,0 +1,116 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/icon.hpp"
#include "guichan/graphics.hpp"
#include "guichan/image.hpp"
#include "guichan/rectangle.hpp"
namespace gcn
{
Icon::Icon()
: mImage(0)
, mInternalImage(false)
{
setSize(0, 0);
}
Icon::Icon(const std::string& filename)
: mImage(0),
mInternalImage(false)
{
mImage = Image::load(filename);
mInternalImage = true;
setSize(mImage->getWidth(),
mImage->getHeight());
}
Icon::Icon(const Image* image)
: mImage(image),
mInternalImage(false)
{
setSize(mImage->getWidth(),
mImage->getHeight());
}
Icon::~Icon()
{
if (mInternalImage)
{
delete mImage;
}
}
void Icon::setImage(const Image* image)
{
if (mInternalImage)
{
delete mImage;
}
mImage = image;
mInternalImage = false;
setSize(mImage->getWidth(),
mImage->getHeight());
}
const Image* Icon::getImage() const
{
return mImage;
}
void Icon::draw(Graphics* graphics)
{
if (mImage != NULL)
{
const int x = (getWidth() - mImage->getWidth()) / 2;
const int y = (getHeight() - mImage->getHeight()) / 2;
graphics->drawImage(mImage, x, y);
}
}
}

View File

@@ -0,0 +1,166 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/imagebutton.hpp"
#include "guichan/graphics.hpp"
#include "guichan/image.hpp"
namespace gcn
{
ImageButton::ImageButton()
: mImage(0),
mInternalImage(false)
{
setWidth(0);
setHeight(0);
}
ImageButton::ImageButton(const std::string& filename)
: mImage(0),
mInternalImage(false)
{
mImage = Image::load(filename);
mInternalImage = true;
setWidth(mImage->getWidth() + mImage->getWidth() / 2);
setHeight(mImage->getHeight() + mImage->getHeight() / 2);
}
ImageButton::ImageButton(const Image* image)
: mImage(image),
mInternalImage(false)
{
setWidth(mImage->getWidth() + mImage->getWidth() / 2);
setHeight(mImage->getHeight() + mImage->getHeight() / 2);
}
ImageButton::~ImageButton()
{
if (mInternalImage)
{
delete mImage;
}
}
void ImageButton::setImage(const Image* image)
{
if (mInternalImage)
{
delete mImage;
}
mImage = image;
mInternalImage = false;
}
const Image* ImageButton::getImage() const
{
return mImage;
}
void ImageButton::draw(Graphics* graphics)
{
gcn::Color faceColor = getBaseColor();
gcn::Color highlightColor, shadowColor;
int alpha = getBaseColor().a;
if (isPressed())
{
faceColor = faceColor - 0x303030;
faceColor.a = alpha;
highlightColor = faceColor - 0x303030;
highlightColor.a = alpha;
shadowColor = faceColor + 0x303030;
shadowColor.a = alpha;
}
else
{
highlightColor = faceColor + 0x303030;
highlightColor.a = alpha;
shadowColor = faceColor - 0x303030;
shadowColor.a = alpha;
}
graphics->setColor(faceColor);
graphics->fillRectangle(Rectangle(1,
1,
getDimension().width - 1,
getHeight() - 1));
graphics->setColor(highlightColor);
graphics->drawLine(0, 0, getWidth() - 1, 0);
graphics->drawLine(0, 1, 0, getHeight() - 1);
graphics->setColor(shadowColor);
graphics->drawLine(getWidth() - 1, 1, getWidth() - 1, getHeight() - 1);
graphics->drawLine(1, getHeight() - 1, getWidth() - 1, getHeight() - 1);
graphics->setColor(getForegroundColor());
const int textX = (getWidth() - (mImage ? mImage->getWidth() : 0) ) / 2;
const int textY = (getHeight() - (mImage ? mImage->getHeight() : 0) ) / 2;
if (isPressed())
{
if(mImage)
graphics->drawImage(mImage, textX + 1, textY + 1);
}
else
{
if(mImage)
graphics->drawImage(mImage, textX, textY);
if (isFocused())
{
graphics->drawRectangle(Rectangle(2,
2,
getWidth() - 4,
getHeight() - 4));
}
}
}
}

View File

@@ -0,0 +1,120 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/label.hpp"
#include "guichan/exception.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
namespace gcn
{
Label::Label()
{
mAlignment = Graphics::LEFT;
}
Label::Label(const std::string& caption)
{
mCaption = caption;
mAlignment = Graphics::LEFT;
setWidth(getFont()->getWidth(caption));
setHeight(getFont()->getHeight());
}
const std::string &Label::getCaption() const
{
return mCaption;
}
void Label::setCaption(const std::string& caption)
{
mCaption = caption;
}
void Label::setAlignment(Graphics::Alignment alignment)
{
mAlignment = alignment;
}
Graphics::Alignment Label::getAlignment() const
{
return mAlignment;
}
void Label::draw(Graphics* graphics)
{
int textX;
int textY = getHeight() / 2 - getFont()->getHeight() / 2;
switch (getAlignment())
{
case Graphics::LEFT:
textX = 0;
break;
case Graphics::CENTER:
textX = getWidth() / 2;
break;
case Graphics::RIGHT:
textX = getWidth();
break;
default:
throw GCN_EXCEPTION("Unknown alignment.");
}
graphics->setFont(getFont());
graphics->setColor(getForegroundColor());
graphics->drawText(getCaption(), textX, textY, getAlignment());
}
void Label::adjustSize()
{
setWidth(getFont()->getWidth(getCaption()));
setHeight(getFont()->getHeight());
}
}

View File

@@ -0,0 +1,350 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/listbox.hpp"
#include "guichan/basiccontainer.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/listmodel.hpp"
#include "guichan/mouseinput.hpp"
#include "guichan/selectionlistener.hpp"
namespace gcn
{
ListBox::ListBox()
: mSelected(-1),
mListModel(NULL),
mWrappingEnabled(false)
{
setWidth(100);
setFocusable(true);
addMouseListener(this);
addKeyListener(this);
}
ListBox::ListBox(ListModel *listModel)
: mSelected(-1),
mWrappingEnabled(false)
{
setWidth(100);
setListModel(listModel);
setFocusable(true);
addMouseListener(this);
addKeyListener(this);
}
void ListBox::draw(Graphics* graphics)
{
graphics->setColor(getBackgroundColor());
graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));
if (mListModel == NULL)
{
return;
}
graphics->setColor(getForegroundColor());
graphics->setFont(getFont());
// Check the current clip area so we don't draw unnecessary items
// that are not visible.
const ClipRectangle currentClipArea = graphics->getCurrentClipArea();
int rowHeight = getRowHeight();
// Calculate the number of rows to draw by checking the clip area.
// The addition of two makes covers a partial visible row at the top
// and a partial visible row at the bottom.
int numberOfRows = currentClipArea.height / rowHeight + 2;
if (numberOfRows > mListModel->getNumberOfElements())
{
numberOfRows = mListModel->getNumberOfElements();
}
// Calculate which row to start drawing. If the list box
// has a negative y coordinate value we should check if
// we should drop rows in the begining of the list as
// they might not be visible. A negative y value is very
// common if the list box for instance resides in a scroll
// area and the user has scrolled the list box downwards.
int startRow;
if (getY() < 0)
{
startRow = -1 * (getY() / rowHeight);
}
else
{
startRow = 0;
}
int i;
// The y coordinate where we start to draw the text is
// simply the y coordinate multiplied with the font height.
int y = rowHeight * startRow;
for (i = startRow; i < startRow + numberOfRows; ++i)
{
if (i == mSelected)
{
graphics->setColor(getSelectionColor());
graphics->fillRectangle(Rectangle(0, y, getWidth(), rowHeight));
graphics->setColor(getForegroundColor());
}
// If the row height is greater than the font height we
// draw the text with a center vertical alignment.
if (rowHeight > getFont()->getHeight())
{
graphics->drawText(mListModel->getElementAt(i), 1, y + rowHeight / 2 - getFont()->getHeight() / 2);
}
else
{
graphics->drawText(mListModel->getElementAt(i), 1, y);
}
y += rowHeight;
}
}
void ListBox::logic()
{
adjustSize();
}
int ListBox::getSelected() const
{
return mSelected;
}
void ListBox::setSelected(int selected)
{
if (mListModel == NULL)
{
mSelected = -1;
}
else
{
if (selected < 0)
{
mSelected = -1;
}
else if (selected >= mListModel->getNumberOfElements())
{
mSelected = mListModel->getNumberOfElements() - 1;
}
else
{
mSelected = selected;
}
}
Rectangle scroll;
if (mSelected < 0)
{
scroll.y = 0;
}
else
{
scroll.y = getRowHeight() * mSelected;
}
scroll.height = getRowHeight();
showPart(scroll);
distributeValueChangedEvent();
}
void ListBox::keyPressed(KeyEvent& keyEvent)
{
Key key = keyEvent.getKey();
if (key.getValue() == Key::ENTER || key.getValue() == Key::SPACE)
{
distributeActionEvent();
keyEvent.consume();
}
else if (key.getValue() == Key::UP)
{
setSelected(mSelected - 1);
if (mSelected == -1)
{
if (mWrappingEnabled)
{
setSelected(getListModel()->getNumberOfElements() - 1);
}
else
{
setSelected(0);
}
}
keyEvent.consume();
}
else if (key.getValue() == Key::DOWN)
{
if (mWrappingEnabled
&& getSelected() == getListModel()->getNumberOfElements() - 1)
{
setSelected(0);
}
else
{
setSelected(getSelected() + 1);
}
keyEvent.consume();
}
else if (key.getValue() == Key::HOME)
{
setSelected(0);
keyEvent.consume();
}
else if (key.getValue() == Key::END)
{
setSelected(getListModel()->getNumberOfElements() - 1);
keyEvent.consume();
}
}
void ListBox::mousePressed(MouseEvent& mouseEvent)
{
if (mouseEvent.getButton() == MouseEvent::LEFT)
{
setSelected(mouseEvent.getY() / getRowHeight());
distributeActionEvent();
}
}
void ListBox::mouseWheelMovedUp(MouseEvent& mouseEvent)
{
if (isFocused())
{
if (getSelected() > 0 )
{
setSelected(getSelected() - 1);
}
mouseEvent.consume();
}
}
void ListBox::mouseWheelMovedDown(MouseEvent& mouseEvent)
{
if (isFocused())
{
setSelected(getSelected() + 1);
mouseEvent.consume();
}
}
void ListBox::mouseDragged(MouseEvent& mouseEvent)
{
mouseEvent.consume();
}
void ListBox::setListModel(ListModel *listModel)
{
mSelected = -1;
mListModel = listModel;
adjustSize();
}
ListModel* ListBox::getListModel()
{
return mListModel;
}
void ListBox::adjustSize()
{
if (mListModel != NULL)
{
setHeight(getRowHeight() * mListModel->getNumberOfElements());
}
}
bool ListBox::isWrappingEnabled() const
{
return mWrappingEnabled;
}
void ListBox::setWrappingEnabled(bool wrappingEnabled)
{
mWrappingEnabled = wrappingEnabled;
}
void ListBox::addSelectionListener(SelectionListener* selectionListener)
{
mSelectionListeners.push_back(selectionListener);
}
void ListBox::removeSelectionListener(SelectionListener* selectionListener)
{
mSelectionListeners.remove(selectionListener);
}
void ListBox::distributeValueChangedEvent()
{
SelectionListenerIterator iter;
for (iter = mSelectionListeners.begin(); iter != mSelectionListeners.end(); ++iter)
{
SelectionEvent event(this);
(*iter)->valueChanged(event);
}
}
unsigned int ListBox::getRowHeight() const
{
return getFont()->getHeight();
}
}

View File

@@ -0,0 +1,298 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/radiobutton.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/mouseinput.hpp"
namespace gcn
{
RadioButton::GroupMap RadioButton::mGroupMap;
RadioButton::RadioButton()
{
setSelected(false);
setFocusable(true);
addMouseListener(this);
addKeyListener(this);
}
RadioButton::RadioButton(const std::string &caption,
const std::string &group,
bool selected)
{
setCaption(caption);
setGroup(group);
setSelected(selected);
setFocusable(true);
addMouseListener(this);
addKeyListener(this);
adjustSize();
}
RadioButton::~RadioButton()
{
// Remove us from the group list
setGroup("");
}
void RadioButton::draw(Graphics* graphics)
{
graphics->pushClipArea(Rectangle(1,
1,
getWidth() - 1,
getHeight() - 1));
drawBox(graphics);
graphics->popClipArea();
graphics->setFont(getFont());
graphics->setColor(getForegroundColor());
if (isFocused())
{
int fh;
if (getHeight()%2 == 0)
{
fh = getHeight() - 4;
}
else
{
fh = getHeight() - 3;
}
int hh = (fh + 1) / 2;
graphics->drawLine(0, hh + 1, hh + 1, 0);
graphics->drawLine(hh + 2, 1, fh + 2, hh + 1);
graphics->drawLine(fh + 1, hh + 2, hh + 1, fh + 2);
graphics->drawLine(hh + 1, fh + 2, 1, hh + 2);
}
int h = getHeight() + getHeight() / 2;
graphics->drawText(getCaption(), h - 2, 0);
}
void RadioButton::drawBox(Graphics *graphics)
{
int h;
if (getHeight()%2 == 0)
{
h = getHeight() - 4;
}
else
{
h = getHeight() - 3;
}
int alpha = getBaseColor().a;
Color faceColor = getBaseColor();
faceColor.a = alpha;
Color highlightColor = faceColor + 0x303030;
highlightColor.a = alpha;
Color shadowColor = faceColor - 0x303030;
shadowColor.a = alpha;
graphics->setColor(getBackgroundColor());
int i;
int hh = (h + 1) / 2;
for (i = 1; i <= hh; ++i)
{
graphics->drawLine(hh - i + 1,
i,
hh + i - 1,
i);
}
for (i = 1; i < hh; ++i)
{
graphics->drawLine(hh - i + 1,
h - i,
hh + i - 1,
h - i);
}
graphics->setColor(shadowColor);
graphics->drawLine(hh, 0, 0, hh);
graphics->drawLine(hh + 1, 1, h - 1, hh - 1);
graphics->setColor(highlightColor);
graphics->drawLine(1, hh + 1, hh, h);
graphics->drawLine(hh + 1, h - 1, h, hh);
graphics->setColor(getForegroundColor());
int hhh = hh - 3;
if (mSelected)
{
for (i = 0; i < hhh; ++i)
{
graphics->drawLine(hh - i, 4 + i, hh + i, 4 + i);
}
for (i = 0; i < hhh; ++i)
{
graphics->drawLine(hh - i, h - 4 - i, hh + i, h - 4 - i);
}
}
}
bool RadioButton::isSelected() const
{
return mSelected;
}
void RadioButton::setSelected(bool selected)
{
if (selected && mGroup != "")
{
GroupIterator iter, iterEnd;
iterEnd = mGroupMap.upper_bound(mGroup);
for (iter = mGroupMap.lower_bound(mGroup);
iter != iterEnd;
iter++)
{
if (iter->second->isSelected())
{
iter->second->setSelected(false);
}
}
}
mSelected = selected;
}
const std::string &RadioButton::getCaption() const
{
return mCaption;
}
void RadioButton::setCaption(const std::string caption)
{
mCaption = caption;
}
void RadioButton::keyPressed(KeyEvent& keyEvent)
{
Key key = keyEvent.getKey();
if (key.getValue() == Key::ENTER ||
key.getValue() == Key::SPACE)
{
setSelected(true);
distributeActionEvent();
keyEvent.consume();
}
}
void RadioButton::mouseClicked(MouseEvent& mouseEvent)
{
if (mouseEvent.getButton() == MouseEvent::LEFT)
{
setSelected(true);
distributeActionEvent();
}
}
void RadioButton::mouseDragged(MouseEvent& mouseEvent)
{
mouseEvent.consume();
}
void RadioButton::setGroup(const std::string &group)
{
if (mGroup != "")
{
GroupIterator iter, iterEnd;
iterEnd = mGroupMap.upper_bound(mGroup);
for (iter = mGroupMap.lower_bound(mGroup);
iter != iterEnd;
iter++)
{
if (iter->second == this)
{
mGroupMap.erase(iter);
break;
}
}
}
if (group != "")
{
mGroupMap.insert(
std::pair<std::string, RadioButton *>(group, this));
}
mGroup = group;
}
const std::string &RadioButton::getGroup() const
{
return mGroup;
}
void RadioButton::adjustSize()
{
int height = getFont()->getHeight();
setHeight(height);
setWidth(getFont()->getWidth(getCaption()) + height + height/2);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,369 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/slider.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/mouseinput.hpp"
namespace gcn
{
Slider::Slider(double scaleEnd)
{
mDragged = false;
mScaleStart = 0;
mScaleEnd = scaleEnd;
setFocusable(true);
setFrameSize(1);
setOrientation(HORIZONTAL);
setValue(0);
setStepLength(scaleEnd / 10);
setMarkerLength(10);
addMouseListener(this);
addKeyListener(this);
}
Slider::Slider(double scaleStart, double scaleEnd)
{
mDragged = false;
mScaleStart = scaleStart;
mScaleEnd = scaleEnd;
setFocusable(true);
setFrameSize(1);
setOrientation(HORIZONTAL);
setValue(scaleStart);
setStepLength((scaleEnd - scaleStart)/ 10);
setMarkerLength(10);
addMouseListener(this);
addKeyListener(this);
}
void Slider::setScale(double scaleStart, double scaleEnd)
{
mScaleStart = scaleStart;
mScaleEnd = scaleEnd;
}
double Slider::getScaleStart() const
{
return mScaleStart;
}
void Slider::setScaleStart(double scaleStart)
{
mScaleStart = scaleStart;
}
double Slider::getScaleEnd() const
{
return mScaleEnd;
}
void Slider::setScaleEnd(double scaleEnd)
{
mScaleEnd = scaleEnd;
}
void Slider::draw(gcn::Graphics* graphics)
{
Color shadowColor = getBaseColor() - 0x101010;
int alpha = getBaseColor().a;
shadowColor.a = alpha;
graphics->setColor(shadowColor);
graphics->fillRectangle(gcn::Rectangle(0,0,getWidth(),getHeight()));
drawMarker(graphics);
}
void Slider::drawMarker(gcn::Graphics* graphics)
{
gcn::Color faceColor = getBaseColor();
Color highlightColor, shadowColor;
int alpha = getBaseColor().a;
highlightColor = faceColor + 0x303030;
highlightColor.a = alpha;
shadowColor = faceColor - 0x303030;
shadowColor.a = alpha;
graphics->setColor(faceColor);
if (getOrientation() == HORIZONTAL)
{
int v = getMarkerPosition();
graphics->fillRectangle(gcn::Rectangle(v + 1, 1, getMarkerLength() - 2, getHeight() - 2));
graphics->setColor(highlightColor);
graphics->drawLine(v, 0, v + getMarkerLength() - 1,0);
graphics->drawLine(v, 0, v, getHeight() - 1);
graphics->setColor(shadowColor);
graphics->drawLine(v + getMarkerLength() - 1, 1, v + getMarkerLength() - 1, getHeight() - 1);
graphics->drawLine(v + 1, getHeight() - 1, v + getMarkerLength() - 1, getHeight() - 1);
if (isFocused())
{
graphics->setColor(getForegroundColor());
graphics->drawRectangle(Rectangle(v + 2, 2, getMarkerLength() - 4, getHeight() - 4));
}
}
else
{
int v = (getHeight() - getMarkerLength()) - getMarkerPosition();
graphics->fillRectangle(gcn::Rectangle(1, v + 1, getWidth() - 2, getMarkerLength() - 2));
graphics->setColor(highlightColor);
graphics->drawLine(0, v, 0, v + getMarkerLength() - 1);
graphics->drawLine(0, v, getWidth() - 1, v);
graphics->setColor(shadowColor);
graphics->drawLine(1, v + getMarkerLength() - 1, getWidth() - 1, v + getMarkerLength() - 1);
graphics->drawLine(getWidth() - 1, v + 1, getWidth() - 1, v + getMarkerLength() - 1);
if (isFocused())
{
graphics->setColor(getForegroundColor());
graphics->drawRectangle(Rectangle(2, v + 2, getWidth() - 4, getMarkerLength() - 4));
}
}
}
void Slider::mousePressed(MouseEvent& mouseEvent)
{
if (mouseEvent.getButton() == gcn::MouseEvent::LEFT
&& mouseEvent.getX() >= 0
&& mouseEvent.getX() <= getWidth()
&& mouseEvent.getY() >= 0
&& mouseEvent.getY() <= getHeight())
{
if (getOrientation() == HORIZONTAL)
{
setValue(markerPositionToValue(mouseEvent.getX() - getMarkerLength() / 2));
}
else
{
setValue(markerPositionToValue(getHeight() - mouseEvent.getY() - getMarkerLength() / 2));
}
distributeActionEvent();
}
}
void Slider::mouseDragged(MouseEvent& mouseEvent)
{
if (getOrientation() == HORIZONTAL)
{
setValue(markerPositionToValue(mouseEvent.getX() - getMarkerLength() / 2));
}
else
{
setValue(markerPositionToValue(getHeight() - mouseEvent.getY() - getMarkerLength() / 2));
}
distributeActionEvent();
mouseEvent.consume();
}
void Slider::setValue(double value)
{
if (value > getScaleEnd())
{
mValue = getScaleEnd();
return;
}
if (value < getScaleStart())
{
mValue = getScaleStart();
return;
}
mValue = value;
}
double Slider::getValue() const
{
return mValue;
}
int Slider::getMarkerLength() const
{
return mMarkerLength;
}
void Slider::setMarkerLength(int length)
{
mMarkerLength = length;
}
void Slider::keyPressed(KeyEvent& keyEvent)
{
Key key = keyEvent.getKey();
if (getOrientation() == HORIZONTAL)
{
if (key.getValue() == Key::RIGHT)
{
setValue(getValue() + getStepLength());
distributeActionEvent();
keyEvent.consume();
}
else if (key.getValue() == Key::LEFT)
{
setValue(getValue() - getStepLength());
distributeActionEvent();
keyEvent.consume();
}
}
else
{
if (key.getValue() == Key::UP)
{
setValue(getValue() + getStepLength());
distributeActionEvent();
keyEvent.consume();
}
else if (key.getValue() == Key::DOWN)
{
setValue(getValue() - getStepLength());
distributeActionEvent();
keyEvent.consume();
}
}
}
void Slider::setOrientation(Slider::Orientation orientation)
{
mOrientation = orientation;
}
Slider::Orientation Slider::getOrientation() const
{
return mOrientation;
}
double Slider::markerPositionToValue(int v) const
{
int w;
if (getOrientation() == HORIZONTAL)
{
w = getWidth();
}
else
{
w = getHeight();
}
double pos = v / ((double)w - getMarkerLength());
return (1.0 - pos) * getScaleStart() + pos * getScaleEnd();
}
int Slider::valueToMarkerPosition(double value) const
{
int v;
if (getOrientation() == HORIZONTAL)
{
v = getWidth();
}
else
{
v = getHeight();
}
int w = (int)((v - getMarkerLength())
* (value - getScaleStart())
/ (getScaleEnd() - getScaleStart()));
if (w < 0)
{
return 0;
}
if (w > v - getMarkerLength())
{
return v - getMarkerLength();
}
return w;
}
void Slider::setStepLength(double length)
{
mStepLength = length;
}
double Slider::getStepLength() const
{
return mStepLength;
}
int Slider::getMarkerPosition() const
{
return valueToMarkerPosition(getValue());
}
void Slider::mouseWheelMovedUp(MouseEvent& mouseEvent)
{
setValue(getValue() + getStepLength());
distributeActionEvent();
mouseEvent.consume();
}
void Slider::mouseWheelMovedDown(MouseEvent& mouseEvent)
{
setValue(getValue() - getStepLength());
distributeActionEvent();
mouseEvent.consume();
}
}

View File

@@ -0,0 +1,181 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/tab.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/widgets/button.hpp"
#include "guichan/widgets/label.hpp"
#include "guichan/widgets/tabbedarea.hpp"
namespace gcn
{
Tab::Tab()
:mHasMouse(false),
mTabbedArea(NULL)
{
mLabel = new Label();
mLabel->setPosition(4, 4);
add(mLabel);
addMouseListener(this);
}
Tab::~Tab()
{
delete mLabel;
}
void Tab::adjustSize()
{
setSize(mLabel->getWidth() + 8,
mLabel->getHeight() + 8);
if (mTabbedArea != NULL)
{
mTabbedArea->adjustTabPositions();
}
}
void Tab::setTabbedArea(TabbedArea* tabbedArea)
{
mTabbedArea = tabbedArea;
}
TabbedArea* Tab::getTabbedArea()
{
return mTabbedArea;
}
void Tab::setCaption(const std::string& caption)
{
mLabel->setCaption(caption);
mLabel->adjustSize();
adjustSize();
}
const std::string& Tab::getCaption() const
{
return mLabel->getCaption();
}
void Tab::draw(Graphics *graphics)
{
const Color &faceColor = getBaseColor();
const int alpha = getBaseColor().a;
Color highlightColor = faceColor + 0x303030;
highlightColor.a = alpha;
Color shadowColor = faceColor - 0x303030;
shadowColor.a = alpha;
Color borderColor;
Color baseColor;
if ((mTabbedArea != NULL && mTabbedArea->isTabSelected(this))
|| mHasMouse)
{
// Draw a border.
graphics->setColor(highlightColor);
graphics->drawLine(0, 0, getWidth() - 1, 0);
graphics->drawLine(0, 1, 0, getHeight() - 1);
graphics->setColor(shadowColor);
graphics->drawLine(getWidth() - 1, 1, getWidth() - 1, getHeight() - 1);
borderColor = highlightColor;
baseColor = getBaseColor();
}
else
{
// Draw a border.
graphics->setColor(shadowColor);
graphics->drawLine(0, 0, getWidth() - 1, 0);
graphics->drawLine(0, 1, 0, getHeight() - 1);
graphics->drawLine(getWidth() - 1, 1, getWidth() - 1, getHeight() - 1);
baseColor = getBaseColor() - 0x151515;
baseColor.a = alpha;
}
// Push a clip area so the other drawings don't need to worry
// about the border.
graphics->pushClipArea(Rectangle(1, 1, getWidth() - 2, getHeight() - 1));
const Rectangle currentClipArea = graphics->getCurrentClipArea();
graphics->setColor(baseColor);
graphics->fillRectangle(Rectangle(0,
0,
currentClipArea.width,
currentClipArea.height));
drawChildren(graphics);
if (mTabbedArea != NULL
&& mTabbedArea->isFocused()
&& mTabbedArea->isTabSelected(this))
{
graphics->setColor(Color(0x000000));
graphics->drawRectangle(Rectangle(2,
2,
currentClipArea.width - 4,
currentClipArea.height - 4));
}
graphics->popClipArea();
}
void Tab::mouseEntered(MouseEvent& mouseEvent)
{
mHasMouse = true;
}
void Tab::mouseExited(MouseEvent& mouseEvent)
{
mHasMouse = false;
}
}

View File

@@ -0,0 +1,482 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/tabbedarea.hpp"
#include "guichan/exception.hpp"
#include "guichan/focushandler.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/widgets/container.hpp"
#include "guichan/widgets/tab.hpp"
#include <algorithm>
namespace gcn
{
TabbedArea::TabbedArea()
:mSelectedTab(NULL),
mOpaque(false)
{
setFocusable(true);
addKeyListener(this);
addMouseListener(this);
mTabContainer = new Container();
mTabContainer->setOpaque(false);
mWidgetContainer = new Container();
add(mTabContainer);
add(mWidgetContainer);
}
TabbedArea::~TabbedArea()
{
remove(mTabContainer);
remove(mWidgetContainer);
delete mTabContainer;
delete mWidgetContainer;
for (unsigned int i = 0; i < mTabsToDelete.size(); i++)
{
delete mTabsToDelete[i];
}
}
void TabbedArea::addTab(const std::string& caption, Widget* widget)
{
Tab* tab = new Tab();
tab->setCaption(caption);
mTabsToDelete.push_back(tab);
addTab(tab, widget);
}
void TabbedArea::addTab(Tab* tab, Widget* widget)
{
tab->setTabbedArea(this);
tab->addActionListener(this);
mTabContainer->add(tab);
mTabs.push_back(std::pair<Tab*, Widget*>(tab, widget));
if (mSelectedTab == NULL)
{
setSelectedTab(tab);
}
adjustTabPositions();
adjustSize();
}
void TabbedArea::removeTabWithIndex(unsigned int index)
{
if (index >= mTabs.size())
{
throw GCN_EXCEPTION("No such tab index.");
}
removeTab(mTabs[index].first);
}
void TabbedArea::removeTab(Tab* tab)
{
int tabIndexToBeSelected = - 1;
if (tab == mSelectedTab)
{
int index = getSelectedTabIndex();
if (index == (int)mTabs.size() - 1
&& mTabs.size() >= 2)
{
tabIndexToBeSelected = index--;
}
else if (index == (int)mTabs.size() - 1
&& mTabs.size() == 1)
{
tabIndexToBeSelected = -1;
}
else
{
tabIndexToBeSelected = index;
}
}
std::vector<std::pair<Tab*, Widget*> >::iterator iter;
for (iter = mTabs.begin(); iter != mTabs.end(); iter++)
{
if (iter->first == tab)
{
mTabContainer->remove(tab);
mTabs.erase(iter);
break;
}
}
std::vector<Tab*>::iterator iter2;
for (iter2 = mTabsToDelete.begin(); iter2 != mTabsToDelete.end(); iter2++)
{
if (*iter2 == tab)
{
mTabsToDelete.erase(iter2);
delete tab;
break;
}
}
if (tabIndexToBeSelected == -1)
{
mSelectedTab = NULL;
mWidgetContainer->clear();
}
else
{
setSelectedTab(tabIndexToBeSelected);
}
adjustSize();
adjustTabPositions();
}
bool TabbedArea::isTabSelected(unsigned int index) const
{
if (index >= mTabs.size())
{
throw GCN_EXCEPTION("No such tab index.");
}
return mSelectedTab == mTabs[index].first;
}
bool TabbedArea::isTabSelected(Tab* tab)
{
return mSelectedTab == tab;
}
void TabbedArea::setSelectedTab(unsigned int index)
{
if (index >= mTabs.size())
{
throw GCN_EXCEPTION("No such tab index.");
}
setSelectedTab(mTabs[index].first);
}
void TabbedArea::setSelectedTab(Tab* tab)
{
unsigned int i;
for (i = 0; i < mTabs.size(); i++)
{
if (mTabs[i].first == mSelectedTab)
{
mWidgetContainer->remove(mTabs[i].second);
}
}
for (i = 0; i < mTabs.size(); i++)
{
if (mTabs[i].first == tab)
{
mSelectedTab = tab;
mWidgetContainer->add(mTabs[i].second);
}
}
}
int TabbedArea::getSelectedTabIndex() const
{
unsigned int i;
for (i = 0; i < mTabs.size(); i++)
{
if (mTabs[i].first == mSelectedTab)
{
return i;
}
}
return -1;
}
Tab* TabbedArea::getSelectedTab()
{
return mSelectedTab;
}
void TabbedArea::setOpaque(bool opaque)
{
mOpaque = opaque;
}
bool TabbedArea::isOpaque() const
{
return mOpaque;
}
void TabbedArea::draw(Graphics *graphics)
{
const Color &faceColor = getBaseColor();
const int alpha = getBaseColor().a;
Color highlightColor = faceColor + 0x303030;
highlightColor.a = alpha;
Color shadowColor = faceColor - 0x303030;
shadowColor.a = alpha;
// Draw a border.
graphics->setColor(highlightColor);
graphics->drawLine(0,
mTabContainer->getHeight(),
0,
getHeight() - 2);
graphics->setColor(shadowColor);
graphics->drawLine(getWidth() - 1,
mTabContainer->getHeight() + 1,
getWidth() - 1,
getHeight() - 1);
graphics->drawLine(1,
getHeight() - 1,
getWidth() - 1,
getHeight() - 1);
if (isOpaque())
{
graphics->setColor(getBaseColor());
graphics->fillRectangle(Rectangle(1, 1,
getWidth() - 2,
getHeight() - 2));
}
// Draw a line underneath the tabs.
graphics->setColor(highlightColor);
graphics->drawLine(1,
mTabContainer->getHeight(),
getWidth() - 1,
mTabContainer->getHeight());
// If a tab is selected, remove the line right underneath
// the selected tab.
if (mSelectedTab != NULL)
{
graphics->setColor(getBaseColor());
graphics->drawLine(mSelectedTab->getX() + 1,
mTabContainer->getHeight(),
mSelectedTab->getX() + mSelectedTab->getWidth() - 2,
mTabContainer->getHeight());
}
drawChildren(graphics);
}
void TabbedArea::logic()
{
}
void TabbedArea::adjustSize()
{
int maxTabHeight = 0;
for (unsigned int i = 0; i < mTabs.size(); i++)
{
if (mTabs[i].first->getHeight() > maxTabHeight)
{
maxTabHeight = mTabs[i].first->getHeight();
}
}
mTabContainer->setSize(getWidth() - 2,
maxTabHeight);
mWidgetContainer->setPosition(1, maxTabHeight + 1);
mWidgetContainer->setSize(getWidth() - 2,
getHeight() - maxTabHeight - 2);
}
void TabbedArea::adjustTabPositions()
{
int maxTabHeight = 0;
unsigned int i;
for (i = 0; i < mTabs.size(); i++)
{
if (mTabs[i].first->getHeight() > maxTabHeight)
{
maxTabHeight = mTabs[i].first->getHeight();
}
}
int x = 0;
for (i = 0; i < mTabs.size(); i++)
{
Tab* tab = mTabs[i].first;
tab->setPosition(x, maxTabHeight - tab->getHeight());
x += tab->getWidth();
}
}
void TabbedArea::setWidth(int width)
{
Widget::setWidth(width);
adjustSize();
}
void TabbedArea::setHeight(int height)
{
Widget::setHeight(height);
adjustSize();
}
void TabbedArea::setSize(int width, int height)
{
Widget::setSize(width, height);
adjustSize();
}
void TabbedArea::setDimension(const Rectangle& dimension)
{
Widget::setDimension(dimension);
adjustSize();
}
void TabbedArea::keyPressed(KeyEvent& keyEvent)
{
if (keyEvent.isConsumed() || !isFocused())
{
return;
}
if (keyEvent.getKey().getValue() == Key::LEFT)
{
int index = getSelectedTabIndex();
index--;
if (index < 0)
{
return;
}
else
{
setSelectedTab(mTabs[index].first);
}
keyEvent.consume();
}
else if (keyEvent.getKey().getValue() == Key::RIGHT)
{
int index = getSelectedTabIndex();
index++;
if (index >= (int)mTabs.size())
{
return;
}
else
{
setSelectedTab(mTabs[index].first);
}
keyEvent.consume();
}
}
void TabbedArea::mousePressed(MouseEvent& mouseEvent)
{
if (mouseEvent.isConsumed())
{
return;
}
if (mouseEvent.getButton() == MouseEvent::LEFT)
{
Widget* widget = mTabContainer->getWidgetAt(mouseEvent.getX(), mouseEvent.getY());
Tab* tab = dynamic_cast<Tab*>(widget);
if (tab != NULL)
{
setSelectedTab(tab);
}
}
// Request focus only if the source of the event
// is not focusble. If the source of the event
// is focused we don't want to steal the focus.
if (!mouseEvent.getSource()->isFocusable())
{
requestFocus();
}
}
void TabbedArea::death(const Event& event)
{
Tab* tab = dynamic_cast<Tab*>(event.getSource());
if (tab != NULL)
{
removeTab(tab);
}
else
{
BasicContainer::death(event);
}
}
void TabbedArea::action(const ActionEvent& actionEvent)
{
Widget* source = actionEvent.getSource();
Tab* tab = dynamic_cast<Tab*>(source);
if (tab == NULL)
{
throw GCN_EXCEPTION("Received an action from a widget that's not a tab!");
}
setSelectedTab(tab);
}
}

View File

@@ -0,0 +1,517 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/textbox.hpp"
#include "guichan/basiccontainer.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/mouseinput.hpp"
namespace gcn
{
TextBox::TextBox()
{
mCaretColumn = 0;
mCaretRow = 0;
mEditable = true;
mOpaque = true;
setText("");
setFocusable(true);
addMouseListener(this);
addKeyListener(this);
adjustSize();
}
TextBox::TextBox(const std::string& text)
{
mCaretColumn = 0;
mCaretRow = 0;
mEditable = true;
mOpaque = true;
setText(text);
setFocusable(true);
addMouseListener(this);
addKeyListener(this);
adjustSize();
}
void TextBox::setText(const std::string& text)
{
mCaretColumn = 0;
mCaretRow = 0;
mTextRows.clear();
std::string::size_type pos, lastPos = 0;
int length;
do
{
pos = text.find("\n", lastPos);
if (pos != std::string::npos)
{
length = pos - lastPos;
}
else
{
length = text.size() - lastPos;
}
std::string sub = text.substr(lastPos, length);
mTextRows.push_back(sub);
lastPos = pos + 1;
} while (pos != std::string::npos);
adjustSize();
}
void TextBox::draw(Graphics* graphics)
{
unsigned int i;
if (mOpaque)
{
graphics->setColor(getBackgroundColor());
graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));
}
if (isFocused() && isEditable())
{
drawCaret(graphics, getFont()->getWidth(mTextRows[mCaretRow].substr(0, mCaretColumn)), mCaretRow * getFont()->getHeight());
}
graphics->setColor(getForegroundColor());
graphics->setFont(getFont());
for (i = 0; i < mTextRows.size(); i++)
{
// Move the text one pixel so we can have a caret before a letter.
graphics->drawText(mTextRows[i], 1, i * getFont()->getHeight());
}
}
void TextBox::drawCaret(Graphics* graphics, int x, int y)
{
graphics->setColor(getForegroundColor());
graphics->drawLine(x, getFont()->getHeight() + y, x, y);
}
void TextBox::mousePressed(MouseEvent& mouseEvent)
{
if (mouseEvent.getButton() == MouseEvent::LEFT)
{
mCaretRow = mouseEvent.getY() / getFont()->getHeight();
if (mCaretRow >= (int)mTextRows.size())
{
mCaretRow = mTextRows.size() - 1;
}
mCaretColumn = getFont()->getStringIndexAt(mTextRows[mCaretRow], mouseEvent.getX());
}
}
void TextBox::mouseDragged(MouseEvent& mouseEvent)
{
mouseEvent.consume();
}
void TextBox::keyPressed(KeyEvent& keyEvent)
{
Key key = keyEvent.getKey();
if (key.getValue() == Key::LEFT)
{
--mCaretColumn;
if (mCaretColumn < 0)
{
--mCaretRow;
if (mCaretRow < 0)
{
mCaretRow = 0;
mCaretColumn = 0;
}
else
{
mCaretColumn = mTextRows[mCaretRow].size();
}
}
}
else if (key.getValue() == Key::RIGHT)
{
++mCaretColumn;
if (mCaretColumn > (int)mTextRows[mCaretRow].size())
{
++mCaretRow;
if (mCaretRow >= (int)mTextRows.size())
{
mCaretRow = mTextRows.size() - 1;
if (mCaretRow < 0)
{
mCaretRow = 0;
}
mCaretColumn = mTextRows[mCaretRow].size();
}
else
{
mCaretColumn = 0;
}
}
}
else if (key.getValue() == Key::DOWN)
{
setCaretRow(mCaretRow + 1);
}
else if (key.getValue() == Key::UP)
{
setCaretRow(mCaretRow - 1);
}
else if (key.getValue() == Key::HOME)
{
mCaretColumn = 0;
}
else if (key.getValue() == Key::END)
{
mCaretColumn = mTextRows[mCaretRow].size();
}
else if (key.getValue() == Key::ENTER && mEditable)
{
mTextRows.insert(mTextRows.begin() + mCaretRow + 1,
mTextRows[mCaretRow].substr(mCaretColumn, mTextRows[mCaretRow].size() - mCaretColumn));
mTextRows[mCaretRow].resize(mCaretColumn);
++mCaretRow;
mCaretColumn = 0;
}
else if (key.getValue() == Key::BACKSPACE
&& mCaretColumn != 0
&& mEditable)
{
mTextRows[mCaretRow].erase(mCaretColumn - 1, 1);
--mCaretColumn;
}
else if (key.getValue() == Key::BACKSPACE
&& mCaretColumn == 0
&& mCaretRow != 0
&& mEditable)
{
mCaretColumn = mTextRows[mCaretRow - 1].size();
mTextRows[mCaretRow - 1] += mTextRows[mCaretRow];
mTextRows.erase(mTextRows.begin() + mCaretRow);
--mCaretRow;
}
else if (key.getValue() == Key::DELETE
&& mCaretColumn < (int)mTextRows[mCaretRow].size()
&& mEditable)
{
mTextRows[mCaretRow].erase(mCaretColumn, 1);
}
else if (key.getValue() == Key::DELETE
&& mCaretColumn == (int)mTextRows[mCaretRow].size()
&& mCaretRow < ((int)mTextRows.size() - 1)
&& mEditable)
{
mTextRows[mCaretRow] += mTextRows[mCaretRow + 1];
mTextRows.erase(mTextRows.begin() + mCaretRow + 1);
}
else if(key.getValue() == Key::PAGE_UP)
{
Widget* par = getParent();
if (par != NULL)
{
int rowsPerPage = par->getChildrenArea().height / getFont()->getHeight();
mCaretRow -= rowsPerPage;
if (mCaretRow < 0)
{
mCaretRow = 0;
}
}
}
else if(key.getValue() == Key::PAGE_DOWN)
{
Widget* par = getParent();
if (par != NULL)
{
int rowsPerPage = par->getChildrenArea().height / getFont()->getHeight();
mCaretRow += rowsPerPage;
if (mCaretRow >= (int)mTextRows.size())
{
mCaretRow = mTextRows.size() - 1;
}
}
}
else if(key.getValue() == Key::TAB
&& mEditable)
{
mTextRows[mCaretRow].insert(mCaretColumn,std::string(" "));
mCaretColumn += 4;
}
else if (key.isCharacter()
&& mEditable)
{
mTextRows[mCaretRow].insert(mCaretColumn,std::string(1,(char)key.getValue()));
++mCaretColumn;
}
adjustSize();
scrollToCaret();
keyEvent.consume();
}
void TextBox::adjustSize()
{
unsigned int i;
int width = 0;
for (i = 0; i < mTextRows.size(); ++i)
{
int w = getFont()->getWidth(mTextRows[i]);
if (width < w)
{
width = w;
}
}
setWidth(width + 1);
setHeight(getFont()->getHeight() * mTextRows.size());
}
void TextBox::setCaretPosition(unsigned int position)
{
int row;
for (row = 0; row < (int)mTextRows.size(); row++)
{
if (position <= mTextRows[row].size())
{
mCaretRow = row;
mCaretColumn = position;
return; // we are done
}
else
{
position--;
}
}
// position beyond end of text
mCaretRow = mTextRows.size() - 1;
mCaretColumn = mTextRows[mCaretRow].size();
}
unsigned int TextBox::getCaretPosition() const
{
int pos = 0, row;
for (row = 0; row < mCaretRow; row++)
{
pos += mTextRows[row].size();
}
return pos + mCaretColumn;
}
void TextBox::setCaretRowColumn(int row, int column)
{
setCaretRow(row);
setCaretColumn(column);
}
void TextBox::setCaretRow(int row)
{
mCaretRow = row;
if (mCaretRow >= (int)mTextRows.size())
{
mCaretRow = mTextRows.size() - 1;
}
if (mCaretRow < 0)
{
mCaretRow = 0;
}
setCaretColumn(mCaretColumn);
}
unsigned int TextBox::getCaretRow() const
{
return mCaretRow;
}
void TextBox::setCaretColumn(int column)
{
mCaretColumn = column;
if (mCaretColumn > (int)mTextRows[mCaretRow].size())
{
mCaretColumn = mTextRows[mCaretRow].size();
}
if (mCaretColumn < 0)
{
mCaretColumn = 0;
}
}
unsigned int TextBox::getCaretColumn() const
{
return mCaretColumn;
}
const std::string& TextBox::getTextRow(int row) const
{
return mTextRows[row];
}
void TextBox::setTextRow(int row, const std::string& text)
{
mTextRows[row] = text;
if (mCaretRow == row)
{
setCaretColumn(mCaretColumn);
}
adjustSize();
}
unsigned int TextBox::getNumberOfRows() const
{
return mTextRows.size();
}
std::string TextBox::getText() const
{
if (mTextRows.size() == 0)
{
return std::string("");
}
int i;
std::string text;
for (i = 0; i < (int)mTextRows.size() - 1; ++i)
{
text = text + mTextRows[i] + "\n";
}
text = text + mTextRows[i];
return text;
}
void TextBox::fontChanged()
{
adjustSize();
}
void TextBox::scrollToCaret()
{
Rectangle scroll;
scroll.x = getFont()->getWidth(mTextRows[mCaretRow].substr(0, mCaretColumn));
scroll.y = getFont()->getHeight() * mCaretRow;
scroll.width = getFont()->getWidth(" ");
scroll.height = getFont()->getHeight() + 2; // add 2 for some extra space
showPart(scroll);
}
void TextBox::setEditable(bool editable)
{
mEditable = editable;
}
bool TextBox::isEditable() const
{
return mEditable;
}
void TextBox::addRow(const std::string row)
{
mTextRows.push_back(row);
adjustSize();
}
bool TextBox::isOpaque()
{
return mOpaque;
}
void TextBox::setOpaque(bool opaque)
{
mOpaque = opaque;
}
}

View File

@@ -0,0 +1,280 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/textfield.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/mouseinput.hpp"
namespace gcn
{
TextField::TextField()
{
mCaretPosition = 0;
mXScroll = 0;
setFocusable(true);
addMouseListener(this);
addKeyListener(this);
}
TextField::TextField(const std::string& text)
{
mCaretPosition = 0;
mXScroll = 0;
mText = text;
adjustSize();
setFocusable(true);
addMouseListener(this);
addKeyListener(this);
}
void TextField::setText(const std::string& text)
{
if(text.size() < mCaretPosition )
{
mCaretPosition = text.size();
}
mText = text;
}
void TextField::draw(Graphics* graphics)
{
Color faceColor = getBaseColor();
Color highlightColor, shadowColor;
int alpha = getBaseColor().a;
highlightColor = faceColor + 0x303030;
highlightColor.a = alpha;
shadowColor = faceColor - 0x303030;
shadowColor.a = alpha;
// Draw a border.
graphics->setColor(shadowColor);
graphics->drawLine(0, 0, getWidth() - 1, 0);
graphics->drawLine(0, 1, 0, getHeight() - 2);
graphics->setColor(highlightColor);
graphics->drawLine(getWidth() - 1, 1, getWidth() - 1, getHeight() - 1);
graphics->drawLine(0, getHeight() - 1, getWidth() - 1, getHeight() - 1);
// Push a clip area so the other drawings don't need to worry
// about the border.
graphics->pushClipArea(Rectangle(1, 1, getWidth() - 2, getHeight() - 2));
graphics->setColor(getBackgroundColor());
graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));
if (isFocused())
{
graphics->setColor(getSelectionColor());
graphics->drawRectangle(Rectangle(0, 0, getWidth() - 2, getHeight() - 2));
graphics->drawRectangle(Rectangle(1, 1, getWidth() - 4, getHeight() - 4));
}
if (isFocused())
{
drawCaret(graphics, getFont()->getWidth(mText.substr(0, mCaretPosition)) - mXScroll);
}
graphics->setColor(getForegroundColor());
graphics->setFont(getFont());
graphics->drawText(mText, 3 - mXScroll, 1);
graphics->popClipArea();
}
void TextField::drawCaret(Graphics* graphics, int x)
{
// Check the current clip area as a clip area with a different
// size than the widget might have been pushed (which is the
// case in the draw method when we push a clip area after we have
// drawn a border).
const Rectangle clipArea = graphics->getCurrentClipArea();
graphics->setColor(getForegroundColor());
graphics->drawLine(x, clipArea.height - 2, x, 1);
}
void TextField::mousePressed(MouseEvent& mouseEvent)
{
if (mouseEvent.getButton() == MouseEvent::LEFT)
{
mCaretPosition = getFont()->getStringIndexAt(mText, mouseEvent.getX() + mXScroll);
fixScroll();
}
}
void TextField::mouseDragged(MouseEvent& mouseEvent)
{
mouseEvent.consume();
}
void TextField::keyPressed(KeyEvent& keyEvent)
{
Key key = keyEvent.getKey();
if (key.getValue() == Key::LEFT && mCaretPosition > 0)
{
--mCaretPosition;
}
else if (key.getValue() == Key::RIGHT && mCaretPosition < mText.size())
{
++mCaretPosition;
}
else if (key.getValue() == Key::DELETE && mCaretPosition < mText.size())
{
mText.erase(mCaretPosition, 1);
}
else if (key.getValue() == Key::BACKSPACE && mCaretPosition > 0)
{
mText.erase(mCaretPosition - 1, 1);
--mCaretPosition;
}
else if (key.getValue() == Key::ENTER)
{
distributeActionEvent();
}
else if (key.getValue() == Key::HOME)
{
mCaretPosition = 0;
}
else if (key.getValue() == Key::END)
{
mCaretPosition = mText.size();
}
else if (key.isCharacter()
&& key.getValue() != Key::TAB)
{
mText.insert(mCaretPosition, std::string(1,(char)key.getValue()));
++mCaretPosition;
}
if (key.getValue() != Key::TAB)
{
keyEvent.consume();
}
fixScroll();
}
void TextField::adjustSize()
{
setWidth(getFont()->getWidth(mText) + 7);
adjustHeight();
fixScroll();
}
void TextField::adjustHeight()
{
setHeight(getFont()->getHeight() + 4);
}
void TextField::fixScroll()
{
if (isFocused())
{
int caretX = getFont()->getWidth(mText.substr(0, mCaretPosition));
if (caretX - mXScroll >= getWidth() - 4)
{
mXScroll = caretX - getWidth() + 4;
}
else if (caretX - mXScroll <= 0)
{
mXScroll = caretX - getWidth() / 2;
if (mXScroll < 0)
{
mXScroll = 0;
}
}
}
}
void TextField::setCaretPosition(unsigned int position)
{
if (position > mText.size())
{
mCaretPosition = mText.size();
}
else
{
mCaretPosition = position;
}
fixScroll();
}
unsigned int TextField::getCaretPosition() const
{
return mCaretPosition;
}
const std::string& TextField::getText() const
{
return mText;
}
void TextField::fontChanged()
{
fixScroll();
}
}

View File

@@ -0,0 +1,308 @@
/* _______ __ __ __ ______ __ __ _______ __ __
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
*
* Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
*
*
* Per Larsson a.k.a finalman
* Olof Naessén a.k.a jansem/yakslem
*
* Visit: http://guichan.sourceforge.net
*
* License: (BSD)
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Guichan nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* For comments regarding functions please see the header file.
*/
#include "guichan/widgets/window.hpp"
#include "guichan/exception.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/mouseinput.hpp"
namespace gcn
{
Window::Window()
:mMoved(false)
{
setFrameSize(1);
setPadding(2);
setTitleBarHeight(16);
setAlignment(Graphics::CENTER);
addMouseListener(this);
setMovable(true);
setOpaque(true);
}
Window::Window(const std::string& caption)
:mMoved(false)
{
setCaption(caption);
setFrameSize(1);
setPadding(2);
setTitleBarHeight(16);
setAlignment(Graphics::CENTER);
addMouseListener(this);
setMovable(true);
setOpaque(true);
}
Window::~Window()
{
}
void Window::setPadding(unsigned int padding)
{
mPadding = padding;
}
unsigned int Window::getPadding() const
{
return mPadding;
}
void Window::setTitleBarHeight(unsigned int height)
{
mTitleBarHeight = height;
}
unsigned int Window::getTitleBarHeight()
{
return mTitleBarHeight;
}
void Window::setCaption(const std::string& caption)
{
mCaption = caption;
}
const std::string& Window::getCaption() const
{
return mCaption;
}
void Window::setAlignment(Graphics::Alignment alignment)
{
mAlignment = alignment;
}
Graphics::Alignment Window::getAlignment() const
{
return mAlignment;
}
void Window::draw(Graphics* graphics)
{
const Color &faceColor = getBaseColor();
Color highlightColor, shadowColor;
const int alpha = getBaseColor().a;
highlightColor = faceColor + 0x303030;
highlightColor.a = alpha;
shadowColor = faceColor - 0x303030;
shadowColor.a = alpha;
Rectangle d = getChildrenArea();
// Fill the background around the content
graphics->setColor(faceColor);
// Fill top
graphics->fillRectangle(Rectangle(0,0,getWidth(),d.y - 1));
// Fill left
graphics->fillRectangle(Rectangle(0,d.y - 1, d.x - 1, getHeight() - d.y + 1));
// Fill right
graphics->fillRectangle(Rectangle(d.x + d.width + 1,
d.y - 1,
getWidth() - d.x - d.width - 1,
getHeight() - d.y + 1));
// Fill bottom
graphics->fillRectangle(Rectangle(d.x - 1,
d.y + d.height + 1,
d.width + 2,
getHeight() - d.height - d.y - 1));
if (isOpaque())
{
graphics->fillRectangle(d);
}
// Construct a rectangle one pixel bigger than the content
d.x -= 1;
d.y -= 1;
d.width += 2;
d.height += 2;
// Draw a border around the content
graphics->setColor(shadowColor);
// Top line
graphics->drawLine(d.x,
d.y,
d.x + d.width - 2,
d.y);
// Left line
graphics->drawLine(d.x,
d.y + 1,
d.x,
d.y + d.height - 1);
graphics->setColor(highlightColor);
// Right line
graphics->drawLine(d.x + d.width - 1,
d.y,
d.x + d.width - 1,
d.y + d.height - 2);
// Bottom line
graphics->drawLine(d.x + 1,
d.y + d.height - 1,
d.x + d.width - 1,
d.y + d.height - 1);
drawChildren(graphics);
int textX;
int textY;
textY = ((int)getTitleBarHeight() - getFont()->getHeight()) / 2;
switch (getAlignment())
{
case Graphics::LEFT:
textX = 4;
break;
case Graphics::CENTER:
textX = getWidth() / 2;
break;
case Graphics::RIGHT:
textX = getWidth() - 4;
break;
default:
throw GCN_EXCEPTION("Unknown alignment.");
}
graphics->setColor(getForegroundColor());
graphics->setFont(getFont());
graphics->pushClipArea(Rectangle(0, 0, getWidth(), getTitleBarHeight() - 1));
graphics->drawText(getCaption(), textX, textY, getAlignment());
graphics->popClipArea();
}
void Window::mousePressed(MouseEvent& mouseEvent)
{
if (mouseEvent.getSource() != this)
{
return;
}
if (getParent() != NULL)
{
getParent()->moveToTop(this);
}
mDragOffsetX = mouseEvent.getX();
mDragOffsetY = mouseEvent.getY();
mMoved = mouseEvent.getY() <= (int)mTitleBarHeight;
}
void Window::mouseReleased(MouseEvent& mouseEvent)
{
mMoved = false;
}
void Window::mouseDragged(MouseEvent& mouseEvent)
{
if (mouseEvent.isConsumed() || mouseEvent.getSource() != this)
{
return;
}
if (isMovable() && mMoved)
{
setPosition(mouseEvent.getX() - mDragOffsetX + getX(),
mouseEvent.getY() - mDragOffsetY + getY());
}
mouseEvent.consume();
}
Rectangle Window::getChildrenArea()
{
return Rectangle(getPadding(),
getTitleBarHeight(),
getWidth() - getPadding() * 2,
getHeight() - getPadding() - getTitleBarHeight());
}
void Window::setMovable(bool movable)
{
mMovable = movable;
}
bool Window::isMovable() const
{
return mMovable;
}
void Window::setOpaque(bool opaque)
{
mOpaque = opaque;
}
bool Window::isOpaque()
{
return mOpaque;
}
void Window::resizeToContent()
{
WidgetListIterator it;
int w = 0, h = 0;
for (it = mWidgets.begin(); it != mWidgets.end(); it++)
{
if ((*it)->getX() + (*it)->getWidth() > w)
{
w = (*it)->getX() + (*it)->getWidth();
}
if ((*it)->getY() + (*it)->getHeight() > h)
{
h = (*it)->getY() + (*it)->getHeight();
}
}
setSize(w + 2* getPadding(), h + getPadding() + getTitleBarHeight());
}
}