mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-29 19:20:09 +00:00
Merge branch 'timeline' into dev
This commit is contained in:
commit
b5ea9fd7e7
Binary file not shown.
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 11 KiB |
@ -63,6 +63,17 @@
|
||||
<color id="filelist_selected_row_face" value="#2c4c91" />
|
||||
<color id="filelist_disabled_row_text" value="#ffc8c8" />
|
||||
<color id="workspace" value="#7d929e" />
|
||||
<color id="timeline_normal" value="#c6c6c6" />
|
||||
<color id="timeline_normal_text" value="#000000" />
|
||||
<color id="timeline_hover" value="#d9d9d9" />
|
||||
<color id="timeline_hover_text" value="#000000" />
|
||||
<color id="timeline_active" value="#7d929e" />
|
||||
<color id="timeline_active_text" value="#ffffff" />
|
||||
<color id="timeline_active_hover" value="#99b3c2" />
|
||||
<color id="timeline_active_hover_text" value="#ffffff" />
|
||||
<color id="timeline_clicked" value="#536069" />
|
||||
<color id="timeline_clicked_text" value="#ffffff" />
|
||||
<color id="timeline_padding" value="#7d929e" />
|
||||
</colors>
|
||||
|
||||
<cursors>
|
||||
@ -80,14 +91,14 @@
|
||||
<cursor id="size_bl" x="80" y="176" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="size_b" x="80" y="192" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="size_br" x="80" y="208" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_tl" x="240" y="96" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_t" x="240" y="112" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_tr" x="240" y="128" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_l" x="240" y="144" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_r" x="240" y="160" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_bl" x="240" y="176" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_b" x="240" y="192" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_br" x="240" y="208" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_tl" x="240" y="160" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_tr" x="256" y="160" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_l" x="240" y="176" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_r" x="256" y="176" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_t" x="240" y="192" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_b" x="256" y="192" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_bl" x="240" y="208" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="rotate_br" x="256" y="208" w="16" h="16" focusx="8" focusy="8" />
|
||||
<cursor id="eyedropper" x="80" y="224" w="16" h="16" focusx="0" focusy="15" />
|
||||
</cursors>
|
||||
|
||||
@ -259,6 +270,133 @@
|
||||
<part id="drop_down_button_right_selected" x="71" y="48" w1="2" w2="2" w3="3" h1="4" h2="6" h3="6" />
|
||||
<part id="transformation_handle" x="208" y="144" w="5" h="5" />
|
||||
<part id="pivot_handle" x="224" y="144" w="9" h="9" />
|
||||
<part id="timeline_normal" x="240" y="0" w1="2" w2="8" w3="2" h1="2" h2="8" h3="2" />
|
||||
<part id="timeline_active" x="252" y="0" w1="2" w2="8" w3="2" h1="2" h2="8" h3="2" />
|
||||
<part id="timeline_hover" x="264" y="0" w1="2" w2="8" w3="2" h1="2" h2="8" h3="2" />
|
||||
<part id="timeline_active_hover" x="276" y="0" w1="2" w2="8" w3="2" h1="2" h2="8" h3="2" />
|
||||
<part id="timeline_clicked" x="288" y="0" w1="2" w2="8" w3="2" h1="2" h2="8" h3="2" />
|
||||
<part id="timeline_open_eye_normal" x="240" y="12" w="12" h="12" />
|
||||
<part id="timeline_open_eye_active" x="252" y="12" w="12" h="12" />
|
||||
<part id="timeline_closed_eye_normal" x="240" y="24" w="12" h="12" />
|
||||
<part id="timeline_closed_eye_active" x="252" y="24" w="12" h="12" />
|
||||
<part id="timeline_open_padlock_normal" x="240" y="36" w="12" h="12" />
|
||||
<part id="timeline_open_padlock_active" x="252" y="36" w="12" h="12" />
|
||||
<part id="timeline_closed_padlock_normal" x="240" y="48" w="12" h="12" />
|
||||
<part id="timeline_closed_padlock_active" x="252" y="48" w="12" h="12" />
|
||||
<part id="timeline_empty_frame_normal" x="240" y="60" w="12" h="12" />
|
||||
<part id="timeline_empty_frame_active" x="252" y="60" w="12" h="12" />
|
||||
<part id="timeline_keyframe_normal" x="240" y="72" w="12" h="12" />
|
||||
<part id="timeline_keyframe_active" x="252" y="72" w="12" h="12" />
|
||||
<part id="timeline_fromleft_normal" x="240" y="84" w="12" h="12" />
|
||||
<part id="timeline_fromleft_active" x="252" y="84" w="12" h="12" />
|
||||
<part id="timeline_fromright_normal" x="240" y="96" w="12" h="12" />
|
||||
<part id="timeline_fromright_active" x="252" y="96" w="12" h="12" />
|
||||
<part id="timeline_fromboth_normal" x="240" y="108" w="12" h="12" />
|
||||
<part id="timeline_fromboth_active" x="252" y="108" w="12" h="12" />
|
||||
<part id="timeline_gear" x="264" y="12" w="12" h="12" />
|
||||
<part id="timeline_padding" x="276" y="12" w1="2" w2="8" w3="2" h1="2" h2="8" h3="2" />
|
||||
<part id="timeline_padding_tr" x="288" y="12" w1="2" w2="8" w3="2" h1="2" h2="8" h3="2" />
|
||||
<part id="timeline_padding_bl" x="276" y="24" w1="2" w2="8" w3="2" h1="2" h2="8" h3="2" />
|
||||
<part id="timeline_padding_br" x="288" y="24" w1="2" w2="8" w3="2" h1="2" h2="8" h3="2" />
|
||||
</parts>
|
||||
|
||||
<stylesheet>
|
||||
|
||||
<!-- timeline -->
|
||||
<style id="timeline">
|
||||
<background color="timeline_normal" part="timeline_normal" />
|
||||
</style>
|
||||
|
||||
<!-- timeline_box -->
|
||||
<style id="timeline_box">
|
||||
<background color="timeline_normal" part="timeline_normal" />
|
||||
<text color="timeline_normal_text" align="center" valign="middle" />
|
||||
</style>
|
||||
<style id="timeline_box:hover">
|
||||
<background color="timeline_hover" part="timeline_hover" />
|
||||
<text color="timeline_hover_text" />
|
||||
</style>
|
||||
<style id="timeline_box:active">
|
||||
<background color="timeline_active" part="timeline_active" />
|
||||
<text color="timeline_active_text" />
|
||||
</style>
|
||||
<style id="timeline_box:active:hover">
|
||||
<background color="timeline_active_hover" part="timeline_active_hover" />
|
||||
<text color="timeline_active_hover_text" />
|
||||
</style>
|
||||
<style id="timeline_box:clicked">
|
||||
<background color="timeline_clicked" part="timeline_clicked" />
|
||||
<text color="timeline_clicked_text" />
|
||||
</style>
|
||||
|
||||
<!-- timeline_eye -->
|
||||
<style id="timeline_open_eye" base="timeline_box">
|
||||
<icon part="timeline_open_eye_normal" />
|
||||
</style>
|
||||
<style id="timeline_open_eye:active">
|
||||
<icon part="timeline_open_eye_active" />
|
||||
</style>
|
||||
<style id="timeline_closed_eye" base="timeline_box">
|
||||
<icon part="timeline_closed_eye_normal" />
|
||||
</style>
|
||||
<style id="timeline_closed_eye:active">
|
||||
<icon part="timeline_closed_eye_active" />
|
||||
</style>
|
||||
|
||||
<!-- timeline_padlock -->
|
||||
<style id="timeline_open_padlock" base="timeline_box">
|
||||
<icon part="timeline_open_padlock_normal" />
|
||||
</style>
|
||||
<style id="timeline_open_padlock:active">
|
||||
<icon part="timeline_open_padlock_active" />
|
||||
</style>
|
||||
<style id="timeline_closed_padlock" base="timeline_box">
|
||||
<icon part="timeline_closed_padlock_normal" />
|
||||
</style>
|
||||
<style id="timeline_closed_padlock:active">
|
||||
<icon part="timeline_closed_padlock_active" />
|
||||
</style>
|
||||
|
||||
<!-- timeline_layer -->
|
||||
<style id="timeline_layer" base="timeline_box">
|
||||
<text align="left" valign="middle" padding-left="4" />
|
||||
</style>
|
||||
|
||||
<!-- timeline_empty_frame -->
|
||||
<style id="timeline_empty_frame" base="timeline_box">
|
||||
<icon part="timeline_empty_frame_normal" />
|
||||
</style>
|
||||
<style id="timeline_empty_frame:active">
|
||||
<icon part="timeline_empty_frame_active" />
|
||||
</style>
|
||||
|
||||
<!--timeline_keyframe-->
|
||||
<style id="timeline_keyframe" base="timeline_box">
|
||||
<icon part="timeline_keyframe_normal" />
|
||||
</style>
|
||||
<style id="timeline_keyframe:active">
|
||||
<icon part="timeline_keyframe_active" />
|
||||
</style>
|
||||
|
||||
<!-- timeline_cel -->
|
||||
<style id="timeline_gear" base="timeline_box">
|
||||
<icon part="timeline_gear" />
|
||||
</style>
|
||||
|
||||
<!-- paddings -->
|
||||
<style id="timeline_padding">
|
||||
<background color="timeline_normal" part="timeline_padding" />
|
||||
</style>
|
||||
<style id="timeline_padding_tr">
|
||||
<background color="timeline_normal" part="timeline_padding_tr" />
|
||||
</style>
|
||||
<style id="timeline_padding_bl">
|
||||
<background color="timeline_normal" part="timeline_padding_bl" />
|
||||
</style>
|
||||
<style id="timeline_padding_br">
|
||||
<background color="timeline_normal" part="timeline_padding_br" />
|
||||
</style>
|
||||
|
||||
</stylesheet>
|
||||
|
||||
</skin>
|
||||
|
@ -1,4 +1,4 @@
|
||||
# ASEPRITE
|
||||
# Aseprite
|
||||
# Copyright (C) 2001-2013 David Capello
|
||||
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
@ -11,9 +11,8 @@ if(MSVC)
|
||||
endif(MSVC)
|
||||
|
||||
# Libraries in this directory
|
||||
set(aseprite_libraries app-library raster-lib
|
||||
scripting-lib undo-lib filters-lib ui-lib
|
||||
she gfx-lib base-lib)
|
||||
set(aseprite_libraries app-library css-lib raster-lib scripting-lib
|
||||
undo-lib filters-lib ui-lib she gfx-lib base-lib)
|
||||
|
||||
# Directories where .h files can be found
|
||||
include_directories(. .. ../third_party)
|
||||
@ -150,6 +149,7 @@ endif()
|
||||
add_subdirectory(base)
|
||||
add_subdirectory(filters)
|
||||
add_subdirectory(gfx)
|
||||
add_subdirectory(css)
|
||||
add_subdirectory(raster)
|
||||
add_subdirectory(scripting)
|
||||
add_subdirectory(she)
|
||||
@ -244,6 +244,7 @@ endfunction()
|
||||
find_unittests(base base-lib ${sys_libs})
|
||||
find_unittests(gfx gfx-lib base-lib ${sys_libs})
|
||||
find_unittests(raster raster-lib gfx-lib base-lib ${libs3rdparty} ${sys_libs})
|
||||
find_unittests(css css-lib gfx-lib base-lib ${libs3rdparty} ${sys_libs})
|
||||
find_unittests(ui ui-lib she gfx-lib base-lib ${libs3rdparty} ${sys_libs})
|
||||
find_unittests(file ${all_libs})
|
||||
find_unittests(app ${all_libs})
|
||||
|
@ -15,6 +15,7 @@ because they don't depend on any other component.
|
||||
|
||||
* [allegro](allegro/): Modified version of [Allegro](http://alleg.sourceforge.net/) library, used for keyboard/mouse input, and drawing 2D graphics on screen.
|
||||
* [base](base/): Core/basic stuff, multithreading, utf8, sha1, file system, memory, etc.
|
||||
* [css](css/): Style sheet library.
|
||||
* [gfx](gfx/): Abstract graphics structures like point, size, rectangle, region, color, etc.
|
||||
* [scripting](scripting/): JavaScript engine ([V8](https://code.google.com/p/v8/)).
|
||||
* [undo](undo/): Generic library to manage undo history of undoable actions.
|
||||
|
@ -177,9 +177,12 @@ add_library(app-library
|
||||
ui/palette_view.cpp
|
||||
ui/popup_window_pin.cpp
|
||||
ui/skin/button_icon_impl.cpp
|
||||
ui/skin/skin_part.cpp
|
||||
ui/skin/skin_property.cpp
|
||||
ui/skin/skin_slider_property.cpp
|
||||
ui/skin/skin_theme.cpp
|
||||
ui/skin/style.cpp
|
||||
ui/skin/style_sheet.cpp
|
||||
ui/status_bar.cpp
|
||||
ui/tabs.cpp
|
||||
ui/timeline.cpp
|
||||
|
@ -404,30 +404,17 @@ void setup_mini_look(Widget* widget)
|
||||
|
||||
void setup_look(Widget* widget, LookType lookType)
|
||||
{
|
||||
SharedPtr<SkinProperty> skinProp;
|
||||
|
||||
skinProp = widget->getProperty(SkinProperty::SkinPropertyName);
|
||||
if (skinProp == NULL)
|
||||
skinProp.reset(new SkinProperty);
|
||||
|
||||
SkinPropertyPtr skinProp = get_skin_property(widget);
|
||||
skinProp->setLook(lookType);
|
||||
widget->setProperty(skinProp);
|
||||
}
|
||||
|
||||
void setup_bevels(Widget* widget, int b1, int b2, int b3, int b4)
|
||||
{
|
||||
SharedPtr<SkinProperty> skinProp;
|
||||
|
||||
skinProp = widget->getProperty(SkinProperty::SkinPropertyName);
|
||||
if (skinProp == NULL)
|
||||
skinProp.reset(new SkinProperty);
|
||||
|
||||
SkinPropertyPtr skinProp = get_skin_property(widget);
|
||||
skinProp->setUpperLeft(b1);
|
||||
skinProp->setUpperRight(b2);
|
||||
skinProp->setLowerLeft(b3);
|
||||
skinProp->setLowerRight(b4);
|
||||
|
||||
widget->setProperty(skinProp);
|
||||
}
|
||||
|
||||
// Sets the IconInterface pointer interface of the button to show the
|
||||
|
@ -128,7 +128,7 @@ void ColorSliders::addSlider(Channel channel, const char* labelText, int min, in
|
||||
m_entry.push_back(entry);
|
||||
m_channel.push_back(channel);
|
||||
|
||||
slider->setProperty(PropertyPtr(new SkinSliderProperty(new ColorSliderBgPainter(channel))));
|
||||
slider->setProperty(SkinSliderPropertyPtr(new SkinSliderProperty(new ColorSliderBgPainter(channel))));
|
||||
slider->setDoubleBuffered(true);
|
||||
|
||||
slider->Change.connect(Bind<void>(&ColorSliders::onSliderChange, this, m_slider.size()-1));
|
||||
@ -201,7 +201,7 @@ void ColorSliders::updateSlidersBgColor(const app::Color& color)
|
||||
|
||||
void ColorSliders::updateSliderBgColor(Slider* slider, const app::Color& color)
|
||||
{
|
||||
SharedPtr<SkinSliderProperty> sliderProperty(slider->getProperty("SkinProperty"));
|
||||
SkinSliderPropertyPtr sliderProperty(slider->getProperty(SkinSliderProperty::Name));
|
||||
|
||||
static_cast<ColorSliderBgPainter*>(sliderProperty->getBgPainter())->setColor(color);
|
||||
|
||||
|
@ -31,9 +31,9 @@ namespace app {
|
||||
template<typename Base = ui::Button>
|
||||
class SkinButton : public Base {
|
||||
public:
|
||||
SkinButton(SkinPart partNormal,
|
||||
SkinPart partHot,
|
||||
SkinPart partSelected)
|
||||
SkinButton(SkinParts partNormal,
|
||||
SkinParts partHot,
|
||||
SkinParts partSelected)
|
||||
: Base("")
|
||||
, m_partNormal(partNormal)
|
||||
, m_partHot(partHot)
|
||||
@ -41,9 +41,9 @@ namespace app {
|
||||
{
|
||||
}
|
||||
|
||||
void setParts(SkinPart partNormal,
|
||||
SkinPart partHot,
|
||||
SkinPart partSelected) {
|
||||
void setParts(SkinParts partNormal,
|
||||
SkinParts partHot,
|
||||
SkinParts partSelected) {
|
||||
m_partNormal = partNormal;
|
||||
m_partHot = partHot;
|
||||
m_partSelected = partSelected;
|
||||
@ -55,7 +55,7 @@ namespace app {
|
||||
gfx::Rect bounds(Base::getClientBounds());
|
||||
ui::Graphics* g = ev.getGraphics();
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(Base::getTheme());
|
||||
SkinPart part;
|
||||
SkinParts part;
|
||||
|
||||
if (Base::isSelected())
|
||||
part = m_partSelected;
|
||||
@ -68,9 +68,9 @@ namespace app {
|
||||
}
|
||||
|
||||
private:
|
||||
SkinPart m_partNormal;
|
||||
SkinPart m_partHot;
|
||||
SkinPart m_partSelected;
|
||||
SkinParts m_partNormal;
|
||||
SkinParts m_partHot;
|
||||
SkinParts m_partSelected;
|
||||
};
|
||||
|
||||
} // namespace skin
|
||||
|
63
src/app/ui/skin/skin_part.cpp
Normal file
63
src/app/ui/skin/skin_part.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/ui/skin/skin_part.h"
|
||||
|
||||
#include <allegro.h>
|
||||
|
||||
namespace app {
|
||||
namespace skin {
|
||||
|
||||
SkinPart::SkinPart()
|
||||
{
|
||||
}
|
||||
|
||||
SkinPart::~SkinPart()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void SkinPart::clear()
|
||||
{
|
||||
for (Bitmaps::iterator it = m_bitmaps.begin(), end = m_bitmaps.end();
|
||||
it != end; ++it) {
|
||||
destroy_bitmap(*it);
|
||||
*it = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SkinPart::setBitmap(size_t index, BITMAP* bitmap)
|
||||
{
|
||||
if (index >= m_bitmaps.size())
|
||||
m_bitmaps.resize(index+1, NULL);
|
||||
|
||||
if (m_bitmaps[index] == bitmap)
|
||||
return;
|
||||
|
||||
if (m_bitmaps[index])
|
||||
destroy_bitmap(m_bitmaps[index]);
|
||||
|
||||
m_bitmaps[index] = bitmap;
|
||||
}
|
||||
|
||||
} // namespace skin
|
||||
} // namespace app
|
54
src/app/ui/skin/skin_part.h
Normal file
54
src/app/ui/skin/skin_part.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef APP_UI_SKIN_SKIN_PART_H_INCLUDED
|
||||
#define APP_UI_SKIN_SKIN_PART_H_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
#include "base/shared_ptr.h"
|
||||
|
||||
struct BITMAP;
|
||||
|
||||
namespace app {
|
||||
namespace skin {
|
||||
|
||||
class SkinPart {
|
||||
public:
|
||||
typedef std::vector<BITMAP*> Bitmaps;
|
||||
|
||||
SkinPart();
|
||||
~SkinPart();
|
||||
|
||||
size_t size() const { return m_bitmaps.size(); }
|
||||
|
||||
void clear();
|
||||
void setBitmap(size_t index, BITMAP* bitmap);
|
||||
BITMAP* getBitmap(size_t index) const {
|
||||
return (index < m_bitmaps.size() ? m_bitmaps[index]: NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
Bitmaps m_bitmaps;
|
||||
};
|
||||
|
||||
typedef SharedPtr<SkinPart> SkinPartPtr;
|
||||
|
||||
} // namespace skin
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -33,7 +33,9 @@ namespace app {
|
||||
name##_W
|
||||
|
||||
// Available parts in the skin sheet
|
||||
enum SkinPart {
|
||||
enum SkinParts {
|
||||
|
||||
PART_NONE,
|
||||
|
||||
PART_RADIO_NORMAL,
|
||||
PART_RADIO_SELECTED,
|
||||
|
@ -22,13 +22,15 @@
|
||||
|
||||
#include "app/ui/skin/skin_property.h"
|
||||
|
||||
#include "ui/widget.h"
|
||||
|
||||
namespace app {
|
||||
namespace skin {
|
||||
|
||||
const char* SkinProperty::SkinPropertyName = "SkinProperty";
|
||||
const char* SkinProperty::Name = "SkinProperty";
|
||||
|
||||
SkinProperty::SkinProperty()
|
||||
: Property(SkinPropertyName)
|
||||
: Property(Name)
|
||||
{
|
||||
m_look = NormalLook;
|
||||
m_upperLeft = 0;
|
||||
@ -41,5 +43,18 @@ SkinProperty::~SkinProperty()
|
||||
{
|
||||
}
|
||||
|
||||
SkinPropertyPtr get_skin_property(ui::Widget* widget)
|
||||
{
|
||||
SkinPropertyPtr skinProp;
|
||||
|
||||
skinProp = widget->getProperty(SkinProperty::Name);
|
||||
if (skinProp == NULL) {
|
||||
skinProp.reset(new SkinProperty);
|
||||
widget->setProperty(skinProp);
|
||||
}
|
||||
|
||||
return skinProp;
|
||||
}
|
||||
|
||||
} // namespace skin
|
||||
} // namespace app
|
||||
|
@ -19,8 +19,13 @@
|
||||
#ifndef APP_UI_SKIN_SKIN_PROPERTY_H_INCLUDED
|
||||
#define APP_UI_SKIN_SKIN_PROPERTY_H_INCLUDED
|
||||
|
||||
#include "base/shared_ptr.h"
|
||||
#include "ui/property.h"
|
||||
|
||||
namespace ui {
|
||||
class Widget;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
namespace skin {
|
||||
|
||||
@ -35,7 +40,7 @@ namespace app {
|
||||
// Property to show widgets with a special look (e.g.: buttons or sliders with mini-borders)
|
||||
class SkinProperty : public ui::Property {
|
||||
public:
|
||||
static const char* SkinPropertyName;
|
||||
static const char* Name;
|
||||
|
||||
SkinProperty();
|
||||
~SkinProperty();
|
||||
@ -61,6 +66,10 @@ namespace app {
|
||||
int m_lowerRight;
|
||||
};
|
||||
|
||||
typedef SharedPtr<SkinProperty> SkinPropertyPtr;
|
||||
|
||||
SkinPropertyPtr get_skin_property(ui::Widget* widget);
|
||||
|
||||
} // namespace skin
|
||||
} // namespace app
|
||||
|
||||
|
@ -25,8 +25,11 @@
|
||||
namespace app {
|
||||
namespace skin {
|
||||
|
||||
const char* SkinSliderProperty::Name = "SkinSliderProperty";
|
||||
|
||||
SkinSliderProperty::SkinSliderProperty(ISliderBgPainter* painter)
|
||||
: m_painter(painter)
|
||||
: Property(Name)
|
||||
, m_painter(painter)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,9 @@
|
||||
#ifndef APP_UI_SKIN_SKIN_SLIDER_PROPERTY_H_INCLUDED
|
||||
#define APP_UI_SKIN_SKIN_SLIDER_PROPERTY_H_INCLUDED
|
||||
|
||||
#include "gfx/rect.h"
|
||||
#include "app/ui/skin/skin_property.h"
|
||||
#include "base/shared_ptr.h"
|
||||
#include "gfx/rect.h"
|
||||
|
||||
namespace ui {
|
||||
class Slider;
|
||||
@ -35,8 +36,10 @@ namespace app {
|
||||
virtual void paint(ui::Slider* slider, ui::Graphics* graphics, const gfx::Rect& rc) = 0;
|
||||
};
|
||||
|
||||
class SkinSliderProperty : public SkinProperty {
|
||||
class SkinSliderProperty : public ui::Property {
|
||||
public:
|
||||
static const char* Name;
|
||||
|
||||
// The given painter is deleted automatically when this
|
||||
// property the destroyed.
|
||||
SkinSliderProperty(ISliderBgPainter* painter);
|
||||
@ -48,6 +51,8 @@ namespace app {
|
||||
ISliderBgPainter* m_painter;
|
||||
};
|
||||
|
||||
typedef SharedPtr<SkinSliderProperty> SkinSliderPropertyPtr;
|
||||
|
||||
} // namespace skin
|
||||
} // namespace app
|
||||
|
||||
|
@ -29,11 +29,14 @@
|
||||
#include "app/ui/skin/skin_property.h"
|
||||
#include "app/ui/skin/skin_slider_property.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/skin/style.h"
|
||||
#include "app/ui/skin/style_sheet.h"
|
||||
#include "app/xml_document.h"
|
||||
#include "app/xml_exception.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/fs.h"
|
||||
#include "base/shared_ptr.h"
|
||||
#include "css/sheet.h"
|
||||
#include "gfx/border.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/rect.h"
|
||||
@ -145,8 +148,7 @@ SkinTheme::SkinTheme()
|
||||
|
||||
// Initialize all graphics in NULL (these bitmaps are loaded from the skin)
|
||||
m_sheet_bmp = NULL;
|
||||
for (int c=0; c<PARTS; ++c)
|
||||
m_part[c] = NULL;
|
||||
m_part.resize(PARTS, NULL);
|
||||
|
||||
sheet_mapping["radio_normal"] = PART_RADIO_NORMAL;
|
||||
sheet_mapping["radio_selected"] = PART_RADIO_SELECTED;
|
||||
@ -348,8 +350,8 @@ SkinTheme::~SkinTheme()
|
||||
for (size_t c=0; c<m_cursors.size(); ++c)
|
||||
delete m_cursors[c];
|
||||
|
||||
for (int c=0; c<PARTS; ++c)
|
||||
destroy_bitmap(m_part[c]);
|
||||
m_part.clear();
|
||||
m_parts_by_id.clear();
|
||||
|
||||
for (std::map<std::string, BITMAP*>::iterator
|
||||
it = m_toolicon.begin(); it != m_toolicon.end(); ++it) {
|
||||
@ -364,7 +366,7 @@ SkinTheme::~SkinTheme()
|
||||
destroy_font(m_minifont);
|
||||
}
|
||||
|
||||
// Call ji_regen_theme after this
|
||||
// Call Theme::regenerate() after this.
|
||||
void SkinTheme::reload_skin()
|
||||
{
|
||||
if (m_sheet_bmp) {
|
||||
@ -417,150 +419,241 @@ void SkinTheme::onRegenerate()
|
||||
{
|
||||
scrollbar_size = 12 * jguiscale();
|
||||
|
||||
m_part.clear();
|
||||
m_part.resize(PARTS, NULL);
|
||||
|
||||
// Load the skin XML
|
||||
std::string xml_filename = "skins/" + m_selected_skin + "/skin.xml";
|
||||
ResourceFinder rf;
|
||||
rf.findInDataDir(xml_filename.c_str());
|
||||
|
||||
while (const char* path = rf.next()) {
|
||||
if (!base::file_exists(path))
|
||||
continue;
|
||||
const char* path;
|
||||
while ((path = rf.next()) &&
|
||||
!base::file_exists(path)) {
|
||||
}
|
||||
if (!path) // not found
|
||||
return;
|
||||
|
||||
XmlDocumentRef doc = open_xml(path);
|
||||
TiXmlHandle handle(doc);
|
||||
XmlDocumentRef doc = open_xml(path);
|
||||
TiXmlHandle handle(doc);
|
||||
|
||||
// Load colors
|
||||
{
|
||||
TiXmlElement* xmlColor = handle
|
||||
.FirstChild("skin")
|
||||
.FirstChild("colors")
|
||||
.FirstChild("color").ToElement();
|
||||
while (xmlColor) {
|
||||
std::string id = xmlColor->Attribute("id");
|
||||
uint32_t value = strtol(xmlColor->Attribute("value")+1, NULL, 16);
|
||||
// Load colors
|
||||
{
|
||||
TiXmlElement* xmlColor = handle
|
||||
.FirstChild("skin")
|
||||
.FirstChild("colors")
|
||||
.FirstChild("color").ToElement();
|
||||
while (xmlColor) {
|
||||
std::string id = xmlColor->Attribute("id");
|
||||
uint32_t value = strtol(xmlColor->Attribute("value")+1, NULL, 16);
|
||||
ui::Color color = ui::rgba((value & 0xff0000) >> 16,
|
||||
(value & 0xff00) >> 8,
|
||||
(value & 0xff));
|
||||
|
||||
std::map<std::string, ThemeColor::Type>::iterator it =
|
||||
color_mapping.find(id);
|
||||
if (it != color_mapping.end()) {
|
||||
m_colors[it->second] = ui::rgba((value & 0xff0000) >> 16,
|
||||
(value & 0xff00) >> 8,
|
||||
(value & 0xff));
|
||||
}
|
||||
PRINTF("Loading color '%s'...\n", id.c_str());
|
||||
|
||||
xmlColor = xmlColor->NextSiblingElement();
|
||||
m_colors_by_id[id] = color;
|
||||
|
||||
std::map<std::string, ThemeColor::Type>::iterator it = color_mapping.find(id);
|
||||
if (it != color_mapping.end()) {
|
||||
m_colors[it->second] = color;
|
||||
}
|
||||
|
||||
xmlColor = xmlColor->NextSiblingElement();
|
||||
}
|
||||
}
|
||||
|
||||
// Load cursors
|
||||
{
|
||||
TiXmlElement* xmlCursor = handle
|
||||
.FirstChild("skin")
|
||||
.FirstChild("cursors")
|
||||
.FirstChild("cursor").ToElement();
|
||||
while (xmlCursor) {
|
||||
std::string id = xmlCursor->Attribute("id");
|
||||
int x = strtol(xmlCursor->Attribute("x"), NULL, 10);
|
||||
int y = strtol(xmlCursor->Attribute("y"), NULL, 10);
|
||||
int w = strtol(xmlCursor->Attribute("w"), NULL, 10);
|
||||
int h = strtol(xmlCursor->Attribute("h"), NULL, 10);
|
||||
int focusx = strtol(xmlCursor->Attribute("focusx"), NULL, 10);
|
||||
int focusy = strtol(xmlCursor->Attribute("focusy"), NULL, 10);
|
||||
int c;
|
||||
// Load cursors
|
||||
{
|
||||
TiXmlElement* xmlCursor = handle
|
||||
.FirstChild("skin")
|
||||
.FirstChild("cursors")
|
||||
.FirstChild("cursor").ToElement();
|
||||
while (xmlCursor) {
|
||||
std::string id = xmlCursor->Attribute("id");
|
||||
int x = strtol(xmlCursor->Attribute("x"), NULL, 10);
|
||||
int y = strtol(xmlCursor->Attribute("y"), NULL, 10);
|
||||
int w = strtol(xmlCursor->Attribute("w"), NULL, 10);
|
||||
int h = strtol(xmlCursor->Attribute("h"), NULL, 10);
|
||||
int focusx = strtol(xmlCursor->Attribute("focusx"), NULL, 10);
|
||||
int focusy = strtol(xmlCursor->Attribute("focusy"), NULL, 10);
|
||||
int c;
|
||||
|
||||
for (c=0; c<kCursorTypes; ++c) {
|
||||
if (id != cursor_names[c])
|
||||
continue;
|
||||
PRINTF("Loading cursor '%s'...\n", id.c_str());
|
||||
|
||||
delete m_cursors[c];
|
||||
m_cursors[c] = NULL;
|
||||
for (c=0; c<kCursorTypes; ++c) {
|
||||
if (id != cursor_names[c])
|
||||
continue;
|
||||
|
||||
BITMAP* bmp = cropPartFromSheet(NULL, x, y, w, h);
|
||||
she::Surface* surface =
|
||||
she::Instance()->createSurfaceFromNativeHandle(reinterpret_cast<void*>(bmp));
|
||||
delete m_cursors[c];
|
||||
m_cursors[c] = NULL;
|
||||
|
||||
m_cursors[c] = new Cursor(surface, gfx::Point(focusx*jguiscale(),
|
||||
focusy*jguiscale()));
|
||||
break;
|
||||
}
|
||||
BITMAP* bmp = cropPartFromSheet(NULL, x, y, w, h);
|
||||
she::Surface* surface =
|
||||
she::Instance()->createSurfaceFromNativeHandle(reinterpret_cast<void*>(bmp));
|
||||
|
||||
if (c == kCursorTypes) {
|
||||
throw base::Exception("Unknown cursor specified in '%s':\n"
|
||||
"<cursor id='%s' ... />\n", xml_filename.c_str(), id.c_str());
|
||||
}
|
||||
|
||||
xmlCursor = xmlCursor->NextSiblingElement();
|
||||
m_cursors[c] = new Cursor(surface, gfx::Point(focusx*jguiscale(),
|
||||
focusy*jguiscale()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Load tool icons
|
||||
{
|
||||
TiXmlElement* xmlIcon = handle
|
||||
.FirstChild("skin")
|
||||
.FirstChild("tools")
|
||||
.FirstChild("tool").ToElement();
|
||||
while (xmlIcon) {
|
||||
// Get the tool-icon rectangle
|
||||
const char* tool_id = xmlIcon->Attribute("id");
|
||||
int x = strtol(xmlIcon->Attribute("x"), NULL, 10);
|
||||
int y = strtol(xmlIcon->Attribute("y"), NULL, 10);
|
||||
int w = strtol(xmlIcon->Attribute("w"), NULL, 10);
|
||||
int h = strtol(xmlIcon->Attribute("h"), NULL, 10);
|
||||
|
||||
// Crop the tool-icon from the sheet
|
||||
m_toolicon[tool_id] = cropPartFromSheet(m_toolicon[tool_id], x, y, w, h);
|
||||
|
||||
xmlIcon = xmlIcon->NextSiblingElement();
|
||||
if (c == kCursorTypes) {
|
||||
throw base::Exception("Unknown cursor specified in '%s':\n"
|
||||
"<cursor id='%s' ... />\n", xml_filename.c_str(), id.c_str());
|
||||
}
|
||||
|
||||
xmlCursor = xmlCursor->NextSiblingElement();
|
||||
}
|
||||
}
|
||||
|
||||
// Load parts
|
||||
{
|
||||
TiXmlElement* xmlPart = handle
|
||||
.FirstChild("skin")
|
||||
.FirstChild("parts")
|
||||
.FirstChild("part").ToElement();
|
||||
while (xmlPart) {
|
||||
// Get the tool-icon rectangle
|
||||
const char* part_id = xmlPart->Attribute("id");
|
||||
int x = strtol(xmlPart->Attribute("x"), NULL, 10);
|
||||
int y = strtol(xmlPart->Attribute("y"), NULL, 10);
|
||||
int w = xmlPart->Attribute("w") ? strtol(xmlPart->Attribute("w"), NULL, 10): 0;
|
||||
int h = xmlPart->Attribute("h") ? strtol(xmlPart->Attribute("h"), NULL, 10): 0;
|
||||
std::map<std::string, int>::iterator it = sheet_mapping.find(part_id);
|
||||
if (it == sheet_mapping.end()) {
|
||||
throw base::Exception("Unknown part specified in '%s':\n"
|
||||
"<part id='%s' ... />\n", xml_filename.c_str(), part_id);
|
||||
}
|
||||
// Load tool icons
|
||||
{
|
||||
TiXmlElement* xmlIcon = handle
|
||||
.FirstChild("skin")
|
||||
.FirstChild("tools")
|
||||
.FirstChild("tool").ToElement();
|
||||
while (xmlIcon) {
|
||||
// Get the tool-icon rectangle
|
||||
const char* tool_id = xmlIcon->Attribute("id");
|
||||
int x = strtol(xmlIcon->Attribute("x"), NULL, 10);
|
||||
int y = strtol(xmlIcon->Attribute("y"), NULL, 10);
|
||||
int w = strtol(xmlIcon->Attribute("w"), NULL, 10);
|
||||
int h = strtol(xmlIcon->Attribute("h"), NULL, 10);
|
||||
|
||||
PRINTF("Loading tool icon '%s'...\n", tool_id);
|
||||
|
||||
// Crop the tool-icon from the sheet
|
||||
m_toolicon[tool_id] = cropPartFromSheet(m_toolicon[tool_id], x, y, w, h);
|
||||
|
||||
xmlIcon = xmlIcon->NextSiblingElement();
|
||||
}
|
||||
}
|
||||
|
||||
// Load parts
|
||||
{
|
||||
TiXmlElement* xmlPart = handle
|
||||
.FirstChild("skin")
|
||||
.FirstChild("parts")
|
||||
.FirstChild("part").ToElement();
|
||||
while (xmlPart) {
|
||||
// Get the tool-icon rectangle
|
||||
const char* part_id = xmlPart->Attribute("id");
|
||||
int x = strtol(xmlPart->Attribute("x"), NULL, 10);
|
||||
int y = strtol(xmlPart->Attribute("y"), NULL, 10);
|
||||
int w = xmlPart->Attribute("w") ? strtol(xmlPart->Attribute("w"), NULL, 10): 0;
|
||||
int h = xmlPart->Attribute("h") ? strtol(xmlPart->Attribute("h"), NULL, 10): 0;
|
||||
|
||||
PRINTF("Loading part '%s'...\n", part_id);
|
||||
|
||||
SkinPartPtr part = m_parts_by_id[part_id];
|
||||
if (part == NULL)
|
||||
part = m_parts_by_id[part_id] = SkinPartPtr(new SkinPart);
|
||||
|
||||
if (w > 0 && h > 0) {
|
||||
part->setBitmap(0, cropPartFromSheet(part->getBitmap(0), x, y, w, h));
|
||||
}
|
||||
else if (xmlPart->Attribute("w1")) { // 3x3-1 part (NW, N, NE, E, SE, S, SW, W)
|
||||
int w1 = strtol(xmlPart->Attribute("w1"), NULL, 10);
|
||||
int w2 = strtol(xmlPart->Attribute("w2"), NULL, 10);
|
||||
int w3 = strtol(xmlPart->Attribute("w3"), NULL, 10);
|
||||
int h1 = strtol(xmlPart->Attribute("h1"), NULL, 10);
|
||||
int h2 = strtol(xmlPart->Attribute("h2"), NULL, 10);
|
||||
int h3 = strtol(xmlPart->Attribute("h3"), NULL, 10);
|
||||
|
||||
part->setBitmap(0, cropPartFromSheet(part->getBitmap(0), x, y, w1, h1)); // NW
|
||||
part->setBitmap(1, cropPartFromSheet(part->getBitmap(1), x+w1, y, w2, h1)); // N
|
||||
part->setBitmap(2, cropPartFromSheet(part->getBitmap(2), x+w1+w2, y, w3, h1)); // NE
|
||||
part->setBitmap(3, cropPartFromSheet(part->getBitmap(3), x+w1+w2, y+h1, w3, h2)); // E
|
||||
part->setBitmap(4, cropPartFromSheet(part->getBitmap(4), x+w1+w2, y+h1+h2, w3, h3)); // SE
|
||||
part->setBitmap(5, cropPartFromSheet(part->getBitmap(5), x+w1, y+h1+h2, w2, h3)); // S
|
||||
part->setBitmap(6, cropPartFromSheet(part->getBitmap(6), x, y+h1+h2, w1, h3)); // SW
|
||||
part->setBitmap(7, cropPartFromSheet(part->getBitmap(7), x, y+h1, w1, h2)); // W
|
||||
}
|
||||
|
||||
// Prepare the m_part vector (which is used for backward
|
||||
// compatibility for widgets that doesn't use SkinStyle).
|
||||
std::map<std::string, int>::iterator it = sheet_mapping.find(part_id);
|
||||
if (it != sheet_mapping.end()) {
|
||||
int c = it->second;
|
||||
|
||||
if (w > 0 && h > 0) {
|
||||
// Crop the part from the sheet
|
||||
m_part[c] = cropPartFromSheet(m_part[c], x, y, w, h);
|
||||
}
|
||||
else if (xmlPart->Attribute("w1")) { // 3x3-1 part (NW, N, NE, E, SE, S, SW, W)
|
||||
int w1 = strtol(xmlPart->Attribute("w1"), NULL, 10);
|
||||
int w2 = strtol(xmlPart->Attribute("w2"), NULL, 10);
|
||||
int w3 = strtol(xmlPart->Attribute("w3"), NULL, 10);
|
||||
int h1 = strtol(xmlPart->Attribute("h1"), NULL, 10);
|
||||
int h2 = strtol(xmlPart->Attribute("h2"), NULL, 10);
|
||||
int h3 = strtol(xmlPart->Attribute("h3"), NULL, 10);
|
||||
|
||||
m_part[c ] = cropPartFromSheet(m_part[c ], x, y, w1, h1); // NW
|
||||
m_part[c+1] = cropPartFromSheet(m_part[c+1], x+w1, y, w2, h1); // N
|
||||
m_part[c+2] = cropPartFromSheet(m_part[c+2], x+w1+w2, y, w3, h1); // NE
|
||||
m_part[c+3] = cropPartFromSheet(m_part[c+3], x+w1+w2, y+h1, w3, h2); // E
|
||||
m_part[c+4] = cropPartFromSheet(m_part[c+4], x+w1+w2, y+h1+h2, w3, h3); // SE
|
||||
m_part[c+5] = cropPartFromSheet(m_part[c+5], x+w1, y+h1+h2, w2, h3); // S
|
||||
m_part[c+6] = cropPartFromSheet(m_part[c+6], x, y+h1+h2, w1, h3); // SW
|
||||
m_part[c+7] = cropPartFromSheet(m_part[c+7], x, y+h1, w1, h2); // W
|
||||
}
|
||||
|
||||
xmlPart = xmlPart->NextSiblingElement();
|
||||
for (size_t i=0; i<part->size(); ++i)
|
||||
m_part[c+i] = part->getBitmap(i);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
xmlPart = xmlPart->NextSiblingElement();
|
||||
}
|
||||
}
|
||||
|
||||
// Load styles
|
||||
{
|
||||
TiXmlElement* xmlStyle = handle
|
||||
.FirstChild("skin")
|
||||
.FirstChild("stylesheet")
|
||||
.FirstChild("style").ToElement();
|
||||
while (xmlStyle) {
|
||||
const char* style_id = xmlStyle->Attribute("id");
|
||||
const char* base_id = xmlStyle->Attribute("base");
|
||||
const css::Style* base = NULL;
|
||||
|
||||
if (base_id)
|
||||
base = m_stylesheet.sheet().getStyle(base_id);
|
||||
|
||||
css::Style* style = new css::Style(style_id, base);
|
||||
m_stylesheet.sheet().addStyle(style);
|
||||
|
||||
TiXmlElement* xmlRule = xmlStyle->FirstChildElement();
|
||||
while (xmlRule) {
|
||||
const std::string ruleName = xmlRule->Value();
|
||||
|
||||
PRINTF("- Rule '%s' for '%s'\n", ruleName.c_str(), style_id);
|
||||
|
||||
// TODO This code design to read styles could be improved.
|
||||
|
||||
const char* part_id = xmlRule->Attribute("part");
|
||||
const char* color_id = xmlRule->Attribute("color");
|
||||
|
||||
// Style align
|
||||
int align = 0;
|
||||
const char* halign = xmlRule->Attribute("align");
|
||||
const char* valign = xmlRule->Attribute("valign");
|
||||
if (halign) {
|
||||
if (strcmp(halign, "left") == 0) align |= JI_LEFT;
|
||||
else if (strcmp(halign, "right") == 0) align |= JI_RIGHT;
|
||||
else if (strcmp(halign, "center") == 0) align |= JI_CENTER;
|
||||
}
|
||||
if (valign) {
|
||||
if (strcmp(valign, "top") == 0) align |= JI_TOP;
|
||||
else if (strcmp(valign, "bottom") == 0) align |= JI_BOTTOM;
|
||||
else if (strcmp(valign, "middle") == 0) align |= JI_MIDDLE;
|
||||
}
|
||||
|
||||
if (ruleName == "background") {
|
||||
if (color_id) (*style)[StyleSheet::backgroundColorRule()] = css::Value(color_id);
|
||||
if (part_id) (*style)[StyleSheet::backgroundPartRule()] = css::Value(part_id);
|
||||
}
|
||||
else if (ruleName == "icon") {
|
||||
if (align) (*style)[StyleSheet::iconAlignRule()] = css::Value(align);
|
||||
if (part_id) (*style)[StyleSheet::iconPartRule()] = css::Value(part_id);
|
||||
}
|
||||
else if (ruleName == "text") {
|
||||
if (color_id) (*style)[StyleSheet::textColorRule()] = css::Value(color_id);
|
||||
if (align) (*style)[StyleSheet::textAlignRule()] = css::Value(align);
|
||||
|
||||
const char* padding_left = xmlRule->Attribute("padding-left");
|
||||
const char* padding_top = xmlRule->Attribute("padding-top");
|
||||
const char* padding_right = xmlRule->Attribute("padding-right");
|
||||
const char* padding_bottom = xmlRule->Attribute("padding-bottom");
|
||||
|
||||
if (padding_left) (*style)[StyleSheet::paddingLeftRule()] = css::Value(strtol(padding_left, NULL, 10));
|
||||
if (padding_top) (*style)[StyleSheet::paddingTopRule()] = css::Value(strtol(padding_top, NULL, 10));
|
||||
if (padding_right) (*style)[StyleSheet::paddingRightRule()] = css::Value(strtol(padding_right, NULL, 10));
|
||||
if (padding_bottom) (*style)[StyleSheet::paddingBottomRule()] = css::Value(strtol(padding_bottom, NULL, 10));
|
||||
}
|
||||
|
||||
xmlRule = xmlRule->NextSiblingElement();
|
||||
}
|
||||
|
||||
xmlStyle = xmlStyle->NextSiblingElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -851,7 +944,7 @@ void SkinTheme::paintButton(PaintEvent& ev)
|
||||
|
||||
// Tool buttons are smaller
|
||||
LookType look = NormalLook;
|
||||
SharedPtr<SkinProperty> skinPropery = widget->getProperty(SkinProperty::SkinPropertyName);
|
||||
SkinPropertyPtr skinPropery = widget->getProperty(SkinProperty::Name);
|
||||
if (skinPropery != NULL)
|
||||
look = skinPropery->getLook();
|
||||
|
||||
@ -926,7 +1019,7 @@ void SkinTheme::paintCheckBox(PaintEvent& ev)
|
||||
|
||||
// Check box look
|
||||
LookType look = NormalLook;
|
||||
SharedPtr<SkinProperty> skinPropery = widget->getProperty(SkinProperty::SkinPropertyName);
|
||||
SkinPropertyPtr skinPropery = widget->getProperty(SkinProperty::Name);
|
||||
if (skinPropery != NULL)
|
||||
look = skinPropery->getLook();
|
||||
|
||||
@ -990,7 +1083,7 @@ void SkinTheme::paintEntry(PaintEvent& ev)
|
||||
y2 = widget->getBounds().y2()-1;
|
||||
|
||||
bool isMiniLook = false;
|
||||
SharedPtr<SkinProperty> skinPropery = widget->getProperty(SkinProperty::SkinPropertyName);
|
||||
SkinPropertyPtr skinPropery = widget->getProperty(SkinProperty::Name);
|
||||
if (skinPropery != NULL)
|
||||
isMiniLook = (skinPropery->getLook() == MiniLook);
|
||||
|
||||
@ -1404,12 +1497,13 @@ void SkinTheme::paintSlider(PaintEvent& ev)
|
||||
// customized background (e.g. RGB sliders)
|
||||
ISliderBgPainter* bgPainter = NULL;
|
||||
|
||||
SharedPtr<SkinProperty> skinPropery = widget->getProperty(SkinProperty::SkinPropertyName);
|
||||
SkinPropertyPtr skinPropery = widget->getProperty(SkinProperty::Name);
|
||||
if (skinPropery != NULL)
|
||||
isMiniLook = (skinPropery->getLook() == MiniLook);
|
||||
|
||||
if (SkinSliderProperty* sliderProperty = dynamic_cast<SkinSliderProperty*>(skinPropery.get()))
|
||||
bgPainter = sliderProperty->getBgPainter();
|
||||
SkinSliderPropertyPtr skinSliderPropery = widget->getProperty(SkinSliderProperty::Name);
|
||||
if (skinSliderPropery != NULL)
|
||||
bgPainter = skinSliderPropery->getBgPainter();
|
||||
|
||||
// Draw customized background
|
||||
if (bgPainter) {
|
||||
@ -2022,53 +2116,82 @@ void SkinTheme::draw_bounds_template(BITMAP* bmp, int x1, int y1, int x2, int y2
|
||||
|
||||
void SkinTheme::draw_bounds_template(Graphics* g, const Rect& rc,
|
||||
int nw, int n, int ne, int e, int se, int s, int sw, int w)
|
||||
{
|
||||
draw_bounds_template(g, rc,
|
||||
m_part[nw],
|
||||
m_part[n],
|
||||
m_part[ne],
|
||||
m_part[e],
|
||||
m_part[se],
|
||||
m_part[s],
|
||||
m_part[sw],
|
||||
m_part[w]);
|
||||
}
|
||||
|
||||
void SkinTheme::draw_bounds_template(ui::Graphics* g, const gfx::Rect& rc, const SkinPartPtr& skinPart)
|
||||
{
|
||||
draw_bounds_template(g, rc,
|
||||
skinPart->getBitmap(0),
|
||||
skinPart->getBitmap(1),
|
||||
skinPart->getBitmap(2),
|
||||
skinPart->getBitmap(3),
|
||||
skinPart->getBitmap(4),
|
||||
skinPart->getBitmap(5),
|
||||
skinPart->getBitmap(6),
|
||||
skinPart->getBitmap(7));
|
||||
}
|
||||
|
||||
void SkinTheme::draw_bounds_template(Graphics* g, const Rect& rc,
|
||||
BITMAP* nw, BITMAP* n, BITMAP* ne,
|
||||
BITMAP* e, BITMAP* se, BITMAP* s,
|
||||
BITMAP* sw, BITMAP* w)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
// Top
|
||||
|
||||
g->drawAlphaBitmap(m_part[nw], rc.x, rc.y);
|
||||
g->drawAlphaBitmap(nw, rc.x, rc.y);
|
||||
|
||||
if (IntersectClip clip = IntersectClip(g, Rect(rc.x+m_part[nw]->w, rc.y,
|
||||
rc.w-m_part[nw]->w-m_part[ne]->w, rc.h))) {
|
||||
for (x = rc.x+m_part[nw]->w;
|
||||
x < rc.x+rc.w-m_part[ne]->w;
|
||||
x += m_part[n]->w) {
|
||||
g->drawAlphaBitmap(m_part[n], x, rc.y);
|
||||
if (IntersectClip clip = IntersectClip(g, Rect(rc.x+nw->w, rc.y,
|
||||
rc.w-nw->w-ne->w, rc.h))) {
|
||||
for (x = rc.x+nw->w;
|
||||
x < rc.x+rc.w-ne->w;
|
||||
x += n->w) {
|
||||
g->drawAlphaBitmap(n, x, rc.y);
|
||||
}
|
||||
}
|
||||
|
||||
g->drawAlphaBitmap(m_part[ne], rc.x+rc.w-m_part[ne]->w, rc.y);
|
||||
g->drawAlphaBitmap(ne, rc.x+rc.w-ne->w, rc.y);
|
||||
|
||||
// Bottom
|
||||
|
||||
g->drawAlphaBitmap(m_part[sw], rc.x, rc.y+rc.h-m_part[sw]->h);
|
||||
g->drawAlphaBitmap(sw, rc.x, rc.y+rc.h-sw->h);
|
||||
|
||||
if (IntersectClip clip = IntersectClip(g, Rect(rc.x+m_part[sw]->w, rc.y,
|
||||
rc.w-m_part[sw]->w-m_part[se]->w, rc.h))) {
|
||||
for (x = rc.x+m_part[sw]->w;
|
||||
x < rc.x+rc.w-m_part[se]->w;
|
||||
x += m_part[s]->w) {
|
||||
g->drawAlphaBitmap(m_part[s], x, rc.y+rc.h-m_part[s]->h);
|
||||
if (IntersectClip clip = IntersectClip(g, Rect(rc.x+sw->w, rc.y,
|
||||
rc.w-sw->w-se->w, rc.h))) {
|
||||
for (x = rc.x+sw->w;
|
||||
x < rc.x+rc.w-se->w;
|
||||
x += s->w) {
|
||||
g->drawAlphaBitmap(s, x, rc.y+rc.h-s->h);
|
||||
}
|
||||
}
|
||||
|
||||
g->drawAlphaBitmap(m_part[se], rc.x+rc.w-m_part[se]->w, rc.y+rc.h-m_part[se]->h);
|
||||
g->drawAlphaBitmap(se, rc.x+rc.w-se->w, rc.y+rc.h-se->h);
|
||||
|
||||
if (IntersectClip clip = IntersectClip(g, Rect(rc.x, rc.y+m_part[nw]->h,
|
||||
rc.w, rc.h-m_part[nw]->h-m_part[sw]->h))) {
|
||||
if (IntersectClip clip = IntersectClip(g, Rect(rc.x, rc.y+nw->h,
|
||||
rc.w, rc.h-nw->h-sw->h))) {
|
||||
// Left
|
||||
for (y = rc.y+m_part[nw]->h;
|
||||
y < rc.y+rc.h-m_part[sw]->h;
|
||||
y += m_part[w]->h) {
|
||||
g->drawAlphaBitmap(m_part[w], rc.x, y);
|
||||
for (y = rc.y+nw->h;
|
||||
y < rc.y+rc.h-sw->h;
|
||||
y += w->h) {
|
||||
g->drawAlphaBitmap(w, rc.x, y);
|
||||
}
|
||||
|
||||
// Right
|
||||
for (y = rc.y+m_part[ne]->h;
|
||||
y < rc.y+rc.h-m_part[se]->h;
|
||||
y += m_part[e]->h) {
|
||||
g->drawAlphaBitmap(m_part[e], rc.x+rc.w-m_part[e]->w, y);
|
||||
for (y = rc.y+ne->h;
|
||||
y < rc.y+rc.h-se->h;
|
||||
y += e->h) {
|
||||
g->drawAlphaBitmap(e, rc.x+rc.w-e->w, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2123,6 +2246,19 @@ void SkinTheme::draw_bounds_nw(Graphics* g, const Rect& rc, int nw, ui::Color bg
|
||||
}
|
||||
}
|
||||
|
||||
void SkinTheme::draw_bounds_nw(ui::Graphics* g, const gfx::Rect& rc, const SkinPartPtr skinPart, ui::Color bg)
|
||||
{
|
||||
draw_bounds_template(g, rc, skinPart);
|
||||
|
||||
// Center
|
||||
if (!is_transparent(bg)) {
|
||||
g->fillRect(bg, Rect(rc).shrink(Border(skinPart->getBitmap(7)->w,
|
||||
skinPart->getBitmap(1)->h,
|
||||
skinPart->getBitmap(3)->w,
|
||||
skinPart->getBitmap(5)->h)));
|
||||
}
|
||||
}
|
||||
|
||||
void SkinTheme::draw_bounds_nw2(Graphics* g, const Rect& rc, int x_mid, int nw1, int nw2, ui::Color bg1, ui::Color bg2)
|
||||
{
|
||||
Rect rc2(rc.x, rc.y, x_mid-rc.x+1, rc.h);
|
||||
|
@ -19,9 +19,13 @@
|
||||
#ifndef APP_UI_SKIN_SKIN_THEME_H_INCLUDED
|
||||
#define APP_UI_SKIN_SKIN_THEME_H_INCLUDED
|
||||
|
||||
#include "gfx/fwd.h"
|
||||
#include "app/ui/skin/skin_part.h"
|
||||
#include "app/ui/skin/skin_parts.h"
|
||||
#include "app/ui/skin/style_sheet.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "gfx/fwd.h"
|
||||
#include "ui/color.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/system.h"
|
||||
#include "ui/theme.h"
|
||||
|
||||
@ -164,6 +168,7 @@ namespace app {
|
||||
void draw_bounds_array(BITMAP* bmp, int x1, int y1, int x2, int y2, int parts[8]);
|
||||
void draw_bounds_nw(BITMAP* bmp, int x1, int y1, int x2, int y2, int nw, ui::Color bg = ui::ColorNone);
|
||||
void draw_bounds_nw(ui::Graphics* g, const gfx::Rect& rc, int nw, ui::Color bg = ui::ColorNone);
|
||||
void draw_bounds_nw(ui::Graphics* g, const gfx::Rect& rc, const SkinPartPtr skinPart, ui::Color bg = ui::ColorNone);
|
||||
void draw_bounds_nw2(ui::Graphics* g, const gfx::Rect& rc, int x_mid, int nw1, int nw2, ui::Color bg1, ui::Color bg2);
|
||||
void draw_part_as_hline(BITMAP* bmp, int x1, int y1, int x2, int y2, int part);
|
||||
void draw_part_as_vline(BITMAP* bmp, int x1, int y1, int x2, int y2, int part);
|
||||
@ -177,14 +182,31 @@ namespace app {
|
||||
|
||||
void drawProgressBar(BITMAP* bmp, int x1, int y1, int x2, int y2, float progress);
|
||||
|
||||
Style* getStyle(const std::string& id) {
|
||||
return m_stylesheet.getStyle(id);
|
||||
}
|
||||
|
||||
SkinPartPtr getPartById(const std::string& id) {
|
||||
return m_parts_by_id[id];
|
||||
}
|
||||
|
||||
ui::Color getColorById(const std::string& id) {
|
||||
return m_colors_by_id[id];
|
||||
}
|
||||
|
||||
protected:
|
||||
void onRegenerate();
|
||||
void onRegenerate() OVERRIDE;
|
||||
|
||||
private:
|
||||
void draw_bounds_template(BITMAP* bmp, int x1, int y1, int x2, int y2,
|
||||
int nw, int n, int ne, int e, int se, int s, int sw, int w);
|
||||
void draw_bounds_template(ui::Graphics* g, const gfx::Rect& rc,
|
||||
int nw, int n, int ne, int e, int se, int s, int sw, int w);
|
||||
void draw_bounds_template(ui::Graphics* g, const gfx::Rect& rc, const SkinPartPtr& skinPart);
|
||||
void draw_bounds_template(ui::Graphics* g, const gfx::Rect& rc,
|
||||
BITMAP* nw, BITMAP* n, BITMAP* ne,
|
||||
BITMAP* e, BITMAP* se, BITMAP* s,
|
||||
BITMAP* sw, BITMAP* w);
|
||||
|
||||
BITMAP* cropPartFromSheet(BITMAP* bmp, int x, int y, int w, int h);
|
||||
ui::Color getWidgetBgColor(ui::Widget* widget);
|
||||
@ -202,13 +224,28 @@ namespace app {
|
||||
|
||||
std::string m_selected_skin;
|
||||
BITMAP* m_sheet_bmp;
|
||||
BITMAP* m_part[PARTS];
|
||||
std::vector<BITMAP*> m_part;
|
||||
std::map<std::string, SkinPartPtr> m_parts_by_id;
|
||||
std::map<std::string, BITMAP*> m_toolicon;
|
||||
std::map<std::string, ui::Color> m_colors_by_id;
|
||||
std::vector<ui::Cursor*> m_cursors;
|
||||
std::vector<ui::Color> m_colors;
|
||||
StyleSheet m_stylesheet;
|
||||
FONT* m_minifont;
|
||||
};
|
||||
|
||||
inline Style* get_style(const std::string& id) {
|
||||
return static_cast<SkinTheme*>(ui::Manager::getDefault()->getTheme())->getStyle(id);
|
||||
}
|
||||
|
||||
inline SkinPartPtr get_part_by_id(const std::string& id) {
|
||||
return static_cast<SkinTheme*>(ui::Manager::getDefault()->getTheme())->getPartById(id);
|
||||
}
|
||||
|
||||
inline ui::Color get_color_by_id(const std::string& id) {
|
||||
return static_cast<SkinTheme*>(ui::Manager::getDefault()->getTheme())->getColorById(id);
|
||||
}
|
||||
|
||||
} // namespace skin
|
||||
} // namespace app
|
||||
|
||||
|
202
src/app/ui/skin/style.cpp
Normal file
202
src/app/ui/skin/style.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/ui/skin/style.h"
|
||||
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "css/sheet.h"
|
||||
#include "ui/graphics.h"
|
||||
#include "ui/theme.h"
|
||||
|
||||
#include <allegro.h>
|
||||
|
||||
namespace app {
|
||||
namespace skin {
|
||||
|
||||
css::State Style::m_hoverState("hover");
|
||||
css::State Style::m_activeState("active");
|
||||
css::State Style::m_clickedState("clicked");
|
||||
|
||||
Rule::~Rule()
|
||||
{
|
||||
}
|
||||
|
||||
void Rule::paint(ui::Graphics* g,
|
||||
const gfx::Rect& bounds,
|
||||
const char* text)
|
||||
{
|
||||
onPaint(g, bounds, text);
|
||||
}
|
||||
|
||||
void BackgroundRule::onPaint(ui::Graphics* g, const gfx::Rect& bounds, const char* text)
|
||||
{
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(ui::CurrentTheme::get());
|
||||
|
||||
if (m_part != NULL && m_part->size() > 0) {
|
||||
if (m_part->size() == 1) {
|
||||
if (!ui::is_transparent(m_color))
|
||||
g->fillRect(m_color, bounds);
|
||||
|
||||
g->drawAlphaBitmap(m_part->getBitmap(0), bounds.x, bounds.y);
|
||||
}
|
||||
else if (m_part->size() == 8) {
|
||||
theme->draw_bounds_nw(g, bounds, m_part, m_color);
|
||||
}
|
||||
}
|
||||
else if (!ui::is_transparent(m_color)) {
|
||||
g->fillRect(m_color, bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void TextRule::onPaint(ui::Graphics* g, const gfx::Rect& bounds, const char* text)
|
||||
{
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(ui::CurrentTheme::get());
|
||||
|
||||
if (text) {
|
||||
g->drawString(text,
|
||||
(ui::is_transparent(m_color) ?
|
||||
theme->getColor(ThemeColor::Text):
|
||||
m_color),
|
||||
ui::ColorNone,
|
||||
gfx::Rect(bounds).shrink(m_padding), m_align);
|
||||
}
|
||||
}
|
||||
|
||||
void IconRule::onPaint(ui::Graphics* g, const gfx::Rect& bounds, const char* text)
|
||||
{
|
||||
BITMAP* bmp = m_part->getBitmap(0);
|
||||
int x, y;
|
||||
|
||||
if (m_align & JI_RIGHT)
|
||||
x = bounds.x2() - bmp->w;
|
||||
else if (m_align & JI_CENTER)
|
||||
x = bounds.x + bounds.w/2 - bmp->w/2;
|
||||
else
|
||||
x = bounds.x;
|
||||
|
||||
if (m_align & JI_BOTTOM)
|
||||
y = bounds.y2() - bmp->h;
|
||||
else if (m_align & JI_MIDDLE)
|
||||
y = bounds.y + bounds.h/2 - bmp->h/2;
|
||||
else
|
||||
y = bounds.y;
|
||||
|
||||
g->drawAlphaBitmap(bmp, x, y);
|
||||
}
|
||||
|
||||
Rules::Rules(const css::Query& query) :
|
||||
m_background(NULL),
|
||||
m_text(NULL),
|
||||
m_icon(NULL)
|
||||
{
|
||||
css::Value backgroundColor = query[StyleSheet::backgroundColorRule()];
|
||||
css::Value backgroundPart = query[StyleSheet::backgroundPartRule()];
|
||||
css::Value iconAlign = query[StyleSheet::iconAlignRule()];
|
||||
css::Value iconPart = query[StyleSheet::iconPartRule()];
|
||||
css::Value textAlign = query[StyleSheet::textAlignRule()];
|
||||
css::Value textColor = query[StyleSheet::textColorRule()];
|
||||
css::Value paddingLeft = query[StyleSheet::paddingLeftRule()];
|
||||
css::Value paddingTop = query[StyleSheet::paddingTopRule()];
|
||||
css::Value paddingRight = query[StyleSheet::paddingRightRule()];
|
||||
css::Value paddingBottom = query[StyleSheet::paddingBottomRule()];
|
||||
css::Value none;
|
||||
|
||||
if (backgroundColor != none
|
||||
|| backgroundPart != none) {
|
||||
m_background = new BackgroundRule();
|
||||
m_background->setColor(StyleSheet::convertColor(backgroundColor));
|
||||
m_background->setPart(StyleSheet::convertPart(backgroundPart));
|
||||
}
|
||||
|
||||
if (iconAlign != none
|
||||
|| iconPart != none) {
|
||||
m_icon = new IconRule();
|
||||
m_icon->setAlign((int)iconAlign.number());
|
||||
m_icon->setPart(StyleSheet::convertPart(iconPart));
|
||||
}
|
||||
|
||||
if (textAlign != none
|
||||
|| textColor != none
|
||||
|| paddingLeft != none
|
||||
|| paddingTop != none
|
||||
|| paddingRight != none
|
||||
|| paddingBottom != none) {
|
||||
m_text = new TextRule();
|
||||
m_text->setAlign((int)textAlign.number());
|
||||
m_text->setColor(StyleSheet::convertColor(textColor));
|
||||
m_text->setPadding(gfx::Border(
|
||||
paddingLeft.number(), paddingTop.number(),
|
||||
paddingRight.number(), paddingBottom.number())*ui::jguiscale());
|
||||
}
|
||||
}
|
||||
|
||||
Rules::~Rules()
|
||||
{
|
||||
delete m_background;
|
||||
delete m_text;
|
||||
delete m_icon;
|
||||
}
|
||||
|
||||
void Rules::paint(ui::Graphics* g,
|
||||
const gfx::Rect& bounds,
|
||||
const char* text)
|
||||
{
|
||||
if (m_background) m_background->paint(g, bounds, text);
|
||||
if (m_icon) m_icon->paint(g, bounds, text);
|
||||
if (m_text) m_text->paint(g, bounds, text);
|
||||
}
|
||||
|
||||
Style::Style(css::Sheet& sheet, const std::string& id)
|
||||
: m_id(id)
|
||||
, m_compoundStyle(sheet.compoundStyle(id))
|
||||
{
|
||||
}
|
||||
|
||||
Style::~Style()
|
||||
{
|
||||
for (RulesMap::iterator it = m_rules.begin(), end = m_rules.end();
|
||||
it != end; ++it) {
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void Style::paint(ui::Graphics* g,
|
||||
const gfx::Rect& bounds,
|
||||
const char* text,
|
||||
const State& state)
|
||||
{
|
||||
Rules* rules = NULL;
|
||||
|
||||
RulesMap::iterator it = m_rules.find(state);
|
||||
if (it != m_rules.end()) {
|
||||
rules = it->second;
|
||||
}
|
||||
else {
|
||||
rules = new Rules(m_compoundStyle[state]);
|
||||
m_rules[state] = rules;
|
||||
}
|
||||
|
||||
rules->paint(g, bounds, text);
|
||||
}
|
||||
|
||||
} // namespace skin
|
||||
} // namespace app
|
154
src/app/ui/skin/style.h
Normal file
154
src/app/ui/skin/style.h
Normal file
@ -0,0 +1,154 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef APP_UI_SKIN_STYLE_H_INCLUDED
|
||||
#define APP_UI_SKIN_STYLE_H_INCLUDED
|
||||
|
||||
#include "app/ui/skin/skin_part.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/disable_copying.h"
|
||||
#include "css/compound_style.h"
|
||||
#include "css/state.h"
|
||||
#include "css/stateful_style.h"
|
||||
#include "gfx/border.h"
|
||||
#include "gfx/fwd.h"
|
||||
#include "ui/color.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ui {
|
||||
class Graphics;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
namespace skin {
|
||||
|
||||
class Rule {
|
||||
public:
|
||||
Rule() { }
|
||||
virtual ~Rule();
|
||||
|
||||
void paint(ui::Graphics* g,
|
||||
const gfx::Rect& bounds,
|
||||
const char* text);
|
||||
|
||||
protected:
|
||||
virtual void onPaint(ui::Graphics* g, const gfx::Rect& bounds, const char* text) = 0;
|
||||
};
|
||||
|
||||
class BackgroundRule : public Rule {
|
||||
public:
|
||||
BackgroundRule() : m_color(ui::ColorNone) { }
|
||||
|
||||
void setColor(ui::Color color) { m_color = color; }
|
||||
void setPart(const SkinPartPtr& part) { m_part = part; }
|
||||
|
||||
protected:
|
||||
void onPaint(ui::Graphics* g, const gfx::Rect& bounds, const char* text) OVERRIDE;
|
||||
|
||||
private:
|
||||
ui::Color m_color;
|
||||
SkinPartPtr m_part;
|
||||
};
|
||||
|
||||
class TextRule : public Rule {
|
||||
public:
|
||||
explicit TextRule() : m_align(0),
|
||||
m_color(ui::ColorNone) { }
|
||||
|
||||
void setAlign(int align) { m_align = align; }
|
||||
void setColor(ui::Color color) { m_color = color; }
|
||||
void setPadding(const gfx::Border& padding) { m_padding = padding; }
|
||||
|
||||
protected:
|
||||
void onPaint(ui::Graphics* g, const gfx::Rect& bounds, const char* text) OVERRIDE;
|
||||
|
||||
private:
|
||||
int m_align;
|
||||
ui::Color m_color;
|
||||
gfx::Border m_padding;
|
||||
};
|
||||
|
||||
class IconRule : public Rule {
|
||||
public:
|
||||
explicit IconRule() : m_align(0) { }
|
||||
|
||||
void setAlign(int align) { m_align = align; }
|
||||
void setPart(const SkinPartPtr& part) { m_part = part; }
|
||||
|
||||
protected:
|
||||
void onPaint(ui::Graphics* g, const gfx::Rect& bounds, const char* text) OVERRIDE;
|
||||
|
||||
private:
|
||||
int m_align;
|
||||
SkinPartPtr m_part;
|
||||
};
|
||||
|
||||
class Rules {
|
||||
public:
|
||||
Rules(const css::Query& query);
|
||||
~Rules();
|
||||
|
||||
void paint(ui::Graphics* g,
|
||||
const gfx::Rect& bounds,
|
||||
const char* text);
|
||||
|
||||
private:
|
||||
BackgroundRule* m_background;
|
||||
TextRule* m_text;
|
||||
IconRule* m_icon;
|
||||
|
||||
DISABLE_COPYING(Rules);
|
||||
};
|
||||
|
||||
class Style {
|
||||
public:
|
||||
typedef css::States State;
|
||||
|
||||
static const css::State& hover() { return m_hoverState; }
|
||||
static const css::State& active() { return m_activeState; }
|
||||
static const css::State& clicked() { return m_clickedState; }
|
||||
|
||||
Style(css::Sheet& sheet, const std::string& id);
|
||||
~Style();
|
||||
|
||||
void paint(ui::Graphics* g,
|
||||
const gfx::Rect& bounds,
|
||||
const char* text,
|
||||
const State& state);
|
||||
|
||||
const std::string& id() const { return m_id; }
|
||||
|
||||
private:
|
||||
typedef std::map<State, Rules*> RulesMap;
|
||||
|
||||
std::string m_id;
|
||||
css::CompoundStyle m_compoundStyle;
|
||||
RulesMap m_rules;
|
||||
|
||||
static css::State m_hoverState;
|
||||
static css::State m_activeState;
|
||||
static css::State m_clickedState;
|
||||
};
|
||||
|
||||
} // namespace skin
|
||||
} // namespace app
|
||||
|
||||
#endif
|
116
src/app/ui/skin/style_sheet.cpp
Normal file
116
src/app/ui/skin/style_sheet.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/ui/skin/style_sheet.h"
|
||||
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/skin/style.h"
|
||||
#include "base/exception.h"
|
||||
#include "css/sheet.h"
|
||||
|
||||
#include "tinyxml.h"
|
||||
|
||||
namespace app {
|
||||
namespace skin {
|
||||
|
||||
css::Rule StyleSheet::m_backgroundColorRule("background-color");
|
||||
css::Rule StyleSheet::m_backgroundPartRule("background-part");
|
||||
css::Rule StyleSheet::m_iconAlignRule("icon-align");
|
||||
css::Rule StyleSheet::m_iconPartRule("icon-part");
|
||||
css::Rule StyleSheet::m_textAlignRule("text-align");
|
||||
css::Rule StyleSheet::m_textColorRule("text-color");
|
||||
css::Rule StyleSheet::m_paddingLeftRule("padding-left");
|
||||
css::Rule StyleSheet::m_paddingTopRule("padding-top");
|
||||
css::Rule StyleSheet::m_paddingRightRule("padding-right");
|
||||
css::Rule StyleSheet::m_paddingBottomRule("padding-bottom");
|
||||
|
||||
StyleSheet::StyleSheet()
|
||||
{
|
||||
m_sheet = new css::Sheet;
|
||||
m_sheet->addRule(&m_backgroundColorRule);
|
||||
m_sheet->addRule(&m_backgroundPartRule);
|
||||
m_sheet->addRule(&m_iconAlignRule);
|
||||
m_sheet->addRule(&m_iconPartRule);
|
||||
m_sheet->addRule(&m_textAlignRule);
|
||||
m_sheet->addRule(&m_textColorRule);
|
||||
m_sheet->addRule(&m_paddingLeftRule);
|
||||
m_sheet->addRule(&m_paddingTopRule);
|
||||
m_sheet->addRule(&m_paddingRightRule);
|
||||
m_sheet->addRule(&m_paddingBottomRule);
|
||||
}
|
||||
|
||||
StyleSheet::~StyleSheet()
|
||||
{
|
||||
destroyAllStyles();
|
||||
delete m_sheet;
|
||||
}
|
||||
|
||||
void StyleSheet::destroyAllStyles()
|
||||
{
|
||||
for (StyleMap::iterator it = m_styles.begin(), end = m_styles.end();
|
||||
it != end; ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
Style* StyleSheet::getStyle(const std::string& id)
|
||||
{
|
||||
Style* style = NULL;
|
||||
|
||||
StyleMap::iterator it = m_styles.find(id);
|
||||
if (it != m_styles.end())
|
||||
style = it->second;
|
||||
else {
|
||||
style = new Style(*m_sheet, id);
|
||||
m_styles[id] = style;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
// static
|
||||
SkinPartPtr StyleSheet::convertPart(const css::Value& value)
|
||||
{
|
||||
SkinPartPtr part;
|
||||
if (value.type() == css::Value::String) {
|
||||
const std::string& part_id = value.string();
|
||||
part = get_part_by_id(part_id);
|
||||
if (part == NULL)
|
||||
throw base::Exception("Unknown part '%s'\n", part_id.c_str());
|
||||
}
|
||||
return part;
|
||||
}
|
||||
|
||||
// static
|
||||
ui::Color StyleSheet::convertColor(const css::Value& value)
|
||||
{
|
||||
ui::Color color;
|
||||
if (value.type() == css::Value::String) {
|
||||
const std::string& color_id = value.string();
|
||||
color = get_color_by_id(color_id);
|
||||
if (color == ui::ColorNone)
|
||||
throw base::Exception("Unknown color '%s'\n", color_id.c_str());
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
} // namespace skin
|
||||
} // namespace app
|
88
src/app/ui/skin/style_sheet.h
Normal file
88
src/app/ui/skin/style_sheet.h
Normal file
@ -0,0 +1,88 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef APP_UI_SKIN_STYLE_SHEET_H_INCLUDED
|
||||
#define APP_UI_SKIN_STYLE_SHEET_H_INCLUDED
|
||||
|
||||
#include "app/ui/skin/skin_part.h"
|
||||
#include "css/rule.h"
|
||||
#include "css/state.h"
|
||||
#include "ui/color.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class TiXmlElement;
|
||||
|
||||
namespace css {
|
||||
class Sheet;
|
||||
class Value;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
namespace skin {
|
||||
|
||||
class Style;
|
||||
|
||||
class StyleSheet {
|
||||
public:
|
||||
StyleSheet();
|
||||
~StyleSheet();
|
||||
|
||||
static css::Rule& backgroundColorRule() { return m_backgroundColorRule; }
|
||||
static css::Rule& backgroundPartRule() { return m_backgroundPartRule; }
|
||||
static css::Rule& iconAlignRule() { return m_iconAlignRule; }
|
||||
static css::Rule& iconPartRule() { return m_iconPartRule; }
|
||||
static css::Rule& textAlignRule() { return m_textAlignRule; }
|
||||
static css::Rule& textColorRule() { return m_textColorRule; }
|
||||
static css::Rule& paddingLeftRule() { return m_paddingLeftRule; }
|
||||
static css::Rule& paddingTopRule() { return m_paddingTopRule; }
|
||||
static css::Rule& paddingRightRule() { return m_paddingRightRule; }
|
||||
static css::Rule& paddingBottomRule() { return m_paddingBottomRule; }
|
||||
|
||||
css::Sheet& sheet() { return *m_sheet; }
|
||||
|
||||
Style* getStyle(const std::string& id);
|
||||
|
||||
static SkinPartPtr convertPart(const css::Value& value);
|
||||
static ui::Color convertColor(const css::Value& value);
|
||||
|
||||
private:
|
||||
typedef std::map<std::string, Style*> StyleMap;
|
||||
|
||||
void destroyAllStyles();
|
||||
|
||||
static css::Rule m_backgroundColorRule;
|
||||
static css::Rule m_backgroundPartRule;
|
||||
static css::Rule m_iconAlignRule;
|
||||
static css::Rule m_iconPartRule;
|
||||
static css::Rule m_textAlignRule;
|
||||
static css::Rule m_textColorRule;
|
||||
static css::Rule m_paddingLeftRule;
|
||||
static css::Rule m_paddingTopRule;
|
||||
static css::Rule m_paddingRightRule;
|
||||
static css::Rule m_paddingBottomRule;
|
||||
|
||||
css::Sheet* m_sheet;
|
||||
StyleMap m_styles;
|
||||
};
|
||||
|
||||
} // namespace skin
|
||||
} // namespace app
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -22,6 +22,7 @@
|
||||
#include "app/context_observer.h"
|
||||
#include "app/document_observer.h"
|
||||
#include "app/ui/editor/editor_observer.h"
|
||||
#include "app/ui/skin/style.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "raster/frame_number.h"
|
||||
#include "ui/widget.h"
|
||||
@ -34,6 +35,10 @@ namespace raster {
|
||||
class Sprite;
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
class Graphics;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
using namespace raster;
|
||||
|
||||
@ -49,6 +54,7 @@ namespace app {
|
||||
enum State {
|
||||
STATE_STANDBY,
|
||||
STATE_SCROLLING,
|
||||
STATE_SELECTING_FRAME,
|
||||
STATE_MOVING_SEPARATOR,
|
||||
STATE_MOVING_LAYER,
|
||||
STATE_MOVING_CEL,
|
||||
@ -74,6 +80,7 @@ namespace app {
|
||||
protected:
|
||||
bool onProcessMessage(ui::Message* msg) OVERRIDE;
|
||||
void onPreferredSize(ui::PreferredSizeEvent& ev) OVERRIDE;
|
||||
void onPaint(ui::PaintEvent& ev) OVERRIDE;
|
||||
|
||||
// DocumentObserver impl.
|
||||
void onAddLayer(DocumentEvent& ev) OVERRIDE;
|
||||
@ -95,18 +102,19 @@ namespace app {
|
||||
private:
|
||||
void detachDocument();
|
||||
void setCursor(int x, int y);
|
||||
void getDrawableLayers(const gfx::Rect& clip, int* first_layer, int* last_layer);
|
||||
void getDrawableFrames(const gfx::Rect& clip, FrameNumber* first_frame, FrameNumber* last_frame);
|
||||
void drawHeader(const gfx::Rect& clip);
|
||||
void drawHeaderFrame(const gfx::Rect& clip, FrameNumber frame);
|
||||
void drawHeaderPart(const gfx::Rect& clip, int x1, int y1, int x2, int y2,
|
||||
bool is_hot, bool is_clk,
|
||||
const char* text, int text_align);
|
||||
void drawSeparator(const gfx::Rect& clip);
|
||||
void drawLayer(const gfx::Rect& clip, int layer_index);
|
||||
void drawLayerPadding();
|
||||
void drawCel(const gfx::Rect& clip, int layer_index, FrameNumber frame, Cel* cel);
|
||||
bool drawPart(int part, int layer, FrameNumber frame);
|
||||
void getDrawableLayers(ui::Graphics* g, int* first_layer, int* last_layer);
|
||||
void getDrawableFrames(ui::Graphics* g, FrameNumber* first_frame, FrameNumber* last_frame);
|
||||
void drawPart(ui::Graphics* g, const gfx::Rect& bounds,
|
||||
const char* text, skin::Style* style,
|
||||
bool is_active = false, bool is_hover = false, bool is_clicked = false);
|
||||
void drawHeader(ui::Graphics* g);
|
||||
void drawHeaderFrame(ui::Graphics* g, FrameNumber frame);
|
||||
void drawLayer(ui::Graphics* g, int layer_index);
|
||||
void drawCel(ui::Graphics* g, int layer_index, FrameNumber frame, Cel* cel);
|
||||
void drawPaddings(ui::Graphics* g);
|
||||
bool drawPart(ui::Graphics* g, int part, int layer, FrameNumber frame);
|
||||
gfx::Rect getPartBounds(int part, int layer = 0, FrameNumber frame = FrameNumber(0)) const;
|
||||
void invalidatePart(int part, int layer, FrameNumber frame);
|
||||
void regenerateLayers();
|
||||
void hotThis(int hot_part, int hot_layer, FrameNumber hotFrame);
|
||||
void centerCel(int layer, FrameNumber frame);
|
||||
@ -114,14 +122,32 @@ namespace app {
|
||||
void showCurrentCel();
|
||||
void cleanClk();
|
||||
void setScroll(int x, int y, bool use_refresh_region);
|
||||
int getLayerIndex(const Layer* layer);
|
||||
int getLayerIndex(const Layer* layer) const;
|
||||
bool isLayerActive(const Layer* layer) const;
|
||||
bool isFrameActive(FrameNumber frame) const;
|
||||
|
||||
skin::Style* m_timelineStyle;
|
||||
skin::Style* m_timelineBoxStyle;
|
||||
skin::Style* m_timelineOpenEyeStyle;
|
||||
skin::Style* m_timelineClosedEyeStyle;
|
||||
skin::Style* m_timelineOpenPadlockStyle;
|
||||
skin::Style* m_timelineClosedPadlockStyle;
|
||||
skin::Style* m_timelineLayerStyle;
|
||||
skin::Style* m_timelineEmptyFrameStyle;
|
||||
skin::Style* m_timelineKeyframeStyle;
|
||||
skin::Style* m_timelineGearStyle;
|
||||
skin::Style* m_timelinePaddingStyle;
|
||||
skin::Style* m_timelinePaddingTrStyle;
|
||||
skin::Style* m_timelinePaddingBlStyle;
|
||||
skin::Style* m_timelinePaddingBrStyle;
|
||||
Context* m_context;
|
||||
Editor* m_editor;
|
||||
Document* m_document;
|
||||
Sprite* m_sprite;
|
||||
Layer* m_layer;
|
||||
FrameNumber m_frame;
|
||||
FrameNumber m_frameBegin;
|
||||
FrameNumber m_frameEnd;
|
||||
State m_state;
|
||||
std::vector<Layer*> m_layers;
|
||||
int m_scroll_x;
|
||||
|
10
src/css/CMakeLists.txt
Normal file
10
src/css/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
# Aseprite CSS Library
|
||||
# Copyright (C) 2013 David Capello
|
||||
|
||||
add_library(css-lib
|
||||
compound_style.cpp
|
||||
query.cpp
|
||||
rule.cpp
|
||||
sheet.cpp
|
||||
style.cpp
|
||||
value.cpp)
|
20
src/css/LICENSE.txt
Normal file
20
src/css/LICENSE.txt
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2001-2013 David Capello
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
4
src/css/README.md
Normal file
4
src/css/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Aseprite CSS Library
|
||||
*Copyright (C) 2013 David Capello*
|
||||
|
||||
> Distributed under [MIT license](LICENSE.txt)
|
69
src/css/compound_style.cpp
Normal file
69
src/css/compound_style.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "css/compound_style.h"
|
||||
|
||||
#include "css/sheet.h"
|
||||
|
||||
namespace css {
|
||||
|
||||
CompoundStyle::CompoundStyle(Sheet* sheet, const std::string& name) :
|
||||
m_sheet(sheet),
|
||||
m_name(name)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void CompoundStyle::update()
|
||||
{
|
||||
deleteQueries();
|
||||
|
||||
const Style* style = m_sheet->getStyle(m_name);
|
||||
if (style)
|
||||
m_normal = m_sheet->query(*style);
|
||||
}
|
||||
|
||||
CompoundStyle::~CompoundStyle()
|
||||
{
|
||||
deleteQueries();
|
||||
}
|
||||
|
||||
void CompoundStyle::deleteQueries()
|
||||
{
|
||||
for (QueriesMap::iterator it = m_queries.begin(), end = m_queries.end();
|
||||
it != end; ++it) {
|
||||
delete it->second;
|
||||
}
|
||||
m_queries.clear();
|
||||
}
|
||||
|
||||
const Value& CompoundStyle::operator[](const Rule& rule) const
|
||||
{
|
||||
return m_normal[rule];
|
||||
}
|
||||
|
||||
const Query& CompoundStyle::operator[](const States& states) const
|
||||
{
|
||||
QueriesMap::const_iterator it = m_queries.find(states);
|
||||
|
||||
if (it != m_queries.end())
|
||||
return *it->second;
|
||||
else {
|
||||
const Style* style = m_sheet->getStyle(m_name);
|
||||
if (style == NULL)
|
||||
return m_normal;
|
||||
|
||||
Query* newQuery = new Query(m_sheet->query(StatefulStyle(*style, states)));
|
||||
m_queries[states] = newQuery;
|
||||
return *newQuery;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace css
|
42
src/css/compound_style.h
Normal file
42
src/css/compound_style.h
Normal file
@ -0,0 +1,42 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifndef CSS_COMPOUND_STYLE_H_INCLUDED
|
||||
#define CSS_COMPOUND_STYLE_H_INCLUDED
|
||||
|
||||
#include "css/query.h"
|
||||
#include "css/rule.h"
|
||||
#include "css/state.h"
|
||||
#include "css/stateful_style.h"
|
||||
|
||||
namespace css {
|
||||
|
||||
class Sheet;
|
||||
|
||||
class CompoundStyle {
|
||||
public:
|
||||
CompoundStyle(Sheet* sheet, const std::string& name);
|
||||
~CompoundStyle();
|
||||
|
||||
void update();
|
||||
|
||||
const Value& operator[](const Rule& rule) const;
|
||||
const Query& operator[](const States& states) const;
|
||||
|
||||
private:
|
||||
typedef std::map<States, Query*> QueriesMap;
|
||||
|
||||
void deleteQueries();
|
||||
|
||||
Sheet* m_sheet;
|
||||
std::string m_name;
|
||||
Query m_normal;
|
||||
mutable QueriesMap m_queries;
|
||||
};
|
||||
|
||||
} // namespace css
|
||||
|
||||
#endif
|
19
src/css/css.h
Normal file
19
src/css/css.h
Normal file
@ -0,0 +1,19 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifndef CSS_CSS_H_INCLUDED
|
||||
#define CSS_CSS_H_INCLUDED
|
||||
|
||||
#include "css/compound_style.h"
|
||||
#include "css/query.h"
|
||||
#include "css/rule.h"
|
||||
#include "css/sheet.h"
|
||||
#include "css/state.h"
|
||||
#include "css/stateful_style.h"
|
||||
#include "css/style.h"
|
||||
#include "css/value.h"
|
||||
|
||||
#endif
|
250
src/css/css_unittest.cpp
Normal file
250
src/css/css_unittest.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "css/css.h"
|
||||
|
||||
using namespace css;
|
||||
using namespace std;
|
||||
|
||||
ostream& operator<<(ostream& os, const Value& value)
|
||||
{
|
||||
os << "(" << value.type();
|
||||
|
||||
if (value.type() == Value::Number)
|
||||
os << ", " << value.number() << " [" << value.unit() << "]";
|
||||
else if (value.type() == Value::String)
|
||||
os << ", " << value.string();
|
||||
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
TEST(Css, Style)
|
||||
{
|
||||
Rule background("background");
|
||||
Rule text("text");
|
||||
Rule border("border");
|
||||
Style style("style");
|
||||
|
||||
style[background] = Value("image.png");
|
||||
style[text] = Value("hi");
|
||||
style[border] = Value(12.0, "px");
|
||||
EXPECT_EQ(Value("image.png"), style[background]);
|
||||
EXPECT_EQ(Value("hi"), style[text]);
|
||||
EXPECT_EQ(Value(12.0, "px"), style[border]);
|
||||
|
||||
style[border].setNumber(13.0);
|
||||
EXPECT_EQ(Value(13.0, "px"), style[border]);
|
||||
|
||||
Style style2("style2", &style);
|
||||
EXPECT_EQ(&style, style2.base());
|
||||
EXPECT_EQ(Value(), style2[background]);
|
||||
EXPECT_EQ(Value(), style2[text]);
|
||||
EXPECT_EQ(Value(), style2[border]);
|
||||
}
|
||||
|
||||
TEST(Css, QueryIsInSyncWithStyleSheet)
|
||||
{
|
||||
Rule background("background");
|
||||
Sheet sheet;
|
||||
sheet.addRule(&background);
|
||||
|
||||
Style style("style");
|
||||
style[background] = Value("a.png");
|
||||
sheet.addStyle(&style);
|
||||
|
||||
Query query = sheet.query(style);
|
||||
EXPECT_EQ(Value("a.png"), query[background]);
|
||||
|
||||
style[background] = Value("b.png");
|
||||
EXPECT_EQ(Value("b.png"), query[background]);
|
||||
}
|
||||
|
||||
TEST(Css, StatefulStyles)
|
||||
{
|
||||
Rule background("background");
|
||||
Rule text("text");
|
||||
Rule border("border");
|
||||
State hover("hover");
|
||||
State focus("focus");
|
||||
State active("active");
|
||||
Style base("base");
|
||||
Style baseHover("base:hover");
|
||||
Style baseFocus("base:focus");
|
||||
Style baseActive("base:active");
|
||||
base[background] = Value("image.png");
|
||||
base[text] = Value("textnormal");
|
||||
baseHover[text] = Value("texthover");
|
||||
baseFocus[border] = Value(12.0);
|
||||
baseActive[border] = Value(24.0);
|
||||
|
||||
Sheet sheet;
|
||||
sheet.addRule(&background);
|
||||
sheet.addRule(&text);
|
||||
sheet.addRule(&border);
|
||||
sheet.addStyle(&base);
|
||||
sheet.addStyle(&baseHover);
|
||||
sheet.addStyle(&baseFocus);
|
||||
sheet.addStyle(&baseActive);
|
||||
|
||||
Query query = sheet.query(base);
|
||||
EXPECT_EQ(Value("image.png"), query[background]);
|
||||
EXPECT_EQ(Value("textnormal"), query[text]);
|
||||
|
||||
query = sheet.query(base + hover);
|
||||
EXPECT_EQ(Value("image.png"), query[background]);
|
||||
EXPECT_EQ(Value("texthover"), query[text]);
|
||||
|
||||
query = sheet.query(base + focus);
|
||||
EXPECT_EQ(Value("image.png"), query[background]);
|
||||
EXPECT_EQ(Value("textnormal"), query[text]);
|
||||
EXPECT_EQ(Value(12.0), query[border]);
|
||||
|
||||
query = sheet.query(base + focus + hover);
|
||||
EXPECT_EQ(Value("image.png"), query[background]);
|
||||
EXPECT_EQ(Value("texthover"), query[text]);
|
||||
EXPECT_EQ(Value(12.0), query[border]);
|
||||
|
||||
query = sheet.query(base + focus + hover + active);
|
||||
EXPECT_EQ(Value("image.png"), query[background]);
|
||||
EXPECT_EQ(Value("texthover"), query[text]);
|
||||
EXPECT_EQ(Value(24.0), query[border]);
|
||||
|
||||
query = sheet.query(base + active + focus + hover); // Different order
|
||||
EXPECT_EQ(Value("image.png"), query[background]);
|
||||
EXPECT_EQ(Value("texthover"), query[text]);
|
||||
EXPECT_EQ(Value(12.0), query[border]);
|
||||
}
|
||||
|
||||
TEST(Css, StyleHierarchy)
|
||||
{
|
||||
Rule bg("bg");
|
||||
Rule fg("fg");
|
||||
State hover("hover");
|
||||
State focus("focus");
|
||||
Style base("base");
|
||||
Style stylea("stylea", &base);
|
||||
Style styleb("styleb", &stylea);
|
||||
Style stylec("stylec", &styleb);
|
||||
base[bg] = Value(1);
|
||||
base[fg] = Value(2);
|
||||
stylea[bg] = Value(3);
|
||||
styleb[bg] = Value(4);
|
||||
styleb[fg] = Value(5);
|
||||
stylec[bg] = Value(6);
|
||||
|
||||
Sheet sheet;
|
||||
sheet.addRule(&bg);
|
||||
sheet.addRule(&fg);
|
||||
sheet.addStyle(&base);
|
||||
sheet.addStyle(&stylea);
|
||||
sheet.addStyle(&styleb);
|
||||
sheet.addStyle(&stylec);
|
||||
|
||||
Query query = sheet.query(base);
|
||||
EXPECT_EQ(Value(1), query[bg]);
|
||||
EXPECT_EQ(Value(2), query[fg]);
|
||||
|
||||
query = sheet.query(stylea);
|
||||
EXPECT_EQ(Value(3), query[bg]);
|
||||
EXPECT_EQ(Value(2), query[fg]);
|
||||
|
||||
query = sheet.query(styleb);
|
||||
EXPECT_EQ(Value(4), query[bg]);
|
||||
EXPECT_EQ(Value(5), query[fg]);
|
||||
|
||||
query = sheet.query(stylec);
|
||||
EXPECT_EQ(Value(6), query[bg]);
|
||||
EXPECT_EQ(Value(5), query[fg]);
|
||||
}
|
||||
|
||||
TEST(Css, CompoundStyles)
|
||||
{
|
||||
Rule bg("bg");
|
||||
Rule fg("fg");
|
||||
State hover("hover");
|
||||
State focus("focus");
|
||||
Style base("base");
|
||||
Style baseHover("base:hover");
|
||||
Style baseFocus("base:focus");
|
||||
Style sub("sub", &base);
|
||||
Style subFocus("sub:focus", &base);
|
||||
Style sub2("sub2", &sub);
|
||||
Style sub3("sub3", &sub2);
|
||||
Style sub3FocusHover("sub3:focus:hover", &sub2);
|
||||
|
||||
base[bg] = Value(1);
|
||||
base[fg] = Value(2);
|
||||
baseHover[fg] = Value(3);
|
||||
baseFocus[bg] = Value(4);
|
||||
|
||||
sub[bg] = Value(5);
|
||||
subFocus[fg] = Value(6);
|
||||
|
||||
sub3[bg] = Value(7);
|
||||
sub3FocusHover[fg] = Value(8);
|
||||
|
||||
Sheet sheet;
|
||||
sheet.addRule(&bg);
|
||||
sheet.addRule(&fg);
|
||||
sheet.addStyle(&base);
|
||||
sheet.addStyle(&baseHover);
|
||||
sheet.addStyle(&baseFocus);
|
||||
sheet.addStyle(&sub);
|
||||
sheet.addStyle(&subFocus);
|
||||
sheet.addStyle(&sub2);
|
||||
sheet.addStyle(&sub3);
|
||||
sheet.addStyle(&sub3FocusHover);
|
||||
|
||||
CompoundStyle compoundBase = sheet.compoundStyle("base");
|
||||
EXPECT_EQ(Value(1), compoundBase[bg]);
|
||||
EXPECT_EQ(Value(2), compoundBase[fg]);
|
||||
EXPECT_EQ(Value(1), compoundBase[hover][bg]);
|
||||
EXPECT_EQ(Value(3), compoundBase[hover][fg]);
|
||||
EXPECT_EQ(Value(4), compoundBase[focus][bg]);
|
||||
EXPECT_EQ(Value(2), compoundBase[focus][fg]);
|
||||
EXPECT_EQ(Value(4), compoundBase[hover+focus][bg]);
|
||||
EXPECT_EQ(Value(3), compoundBase[hover+focus][fg]);
|
||||
|
||||
CompoundStyle compoundSub = sheet.compoundStyle("sub");
|
||||
EXPECT_EQ(Value(5), compoundSub[bg]);
|
||||
EXPECT_EQ(Value(2), compoundSub[fg]);
|
||||
EXPECT_EQ(Value(5), compoundSub[hover][bg]);
|
||||
EXPECT_EQ(Value(3), compoundSub[hover][fg]);
|
||||
EXPECT_EQ(Value(4), compoundSub[focus][bg]);
|
||||
EXPECT_EQ(Value(6), compoundSub[focus][fg]);
|
||||
EXPECT_EQ(Value(4), compoundSub[hover+focus][bg]);
|
||||
EXPECT_EQ(Value(6), compoundSub[hover+focus][fg]);
|
||||
|
||||
CompoundStyle compoundSub2 = sheet.compoundStyle("sub2");
|
||||
EXPECT_EQ(Value(5), compoundSub2[bg]);
|
||||
EXPECT_EQ(Value(2), compoundSub2[fg]);
|
||||
EXPECT_EQ(Value(5), compoundSub2[hover][bg]);
|
||||
EXPECT_EQ(Value(3), compoundSub2[hover][fg]);
|
||||
EXPECT_EQ(Value(4), compoundSub2[focus][bg]);
|
||||
EXPECT_EQ(Value(6), compoundSub2[focus][fg]);
|
||||
EXPECT_EQ(Value(4), compoundSub2[hover+focus][bg]);
|
||||
EXPECT_EQ(Value(6), compoundSub2[hover+focus][fg]);
|
||||
|
||||
CompoundStyle compoundSub3 = sheet.compoundStyle("sub3");
|
||||
EXPECT_EQ(Value(7), compoundSub3[bg]);
|
||||
EXPECT_EQ(Value(2), compoundSub3[fg]);
|
||||
EXPECT_EQ(Value(7), compoundSub3[hover][bg]);
|
||||
EXPECT_EQ(Value(3), compoundSub3[hover][fg]);
|
||||
EXPECT_EQ(Value(4), compoundSub3[focus][bg]);
|
||||
EXPECT_EQ(Value(6), compoundSub3[focus][fg]);
|
||||
EXPECT_EQ(Value(4), compoundSub3[hover+focus][bg]);
|
||||
EXPECT_EQ(Value(6), compoundSub3[hover+focus][fg]);
|
||||
EXPECT_EQ(Value(8), compoundSub3[focus+hover][fg]);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
61
src/css/map.h
Normal file
61
src/css/map.h
Normal file
@ -0,0 +1,61 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifndef CSS_MAP_H_INCLUDED
|
||||
#define CSS_MAP_H_INCLUDED
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace css {
|
||||
|
||||
template<typename T>
|
||||
class Map {
|
||||
public:
|
||||
typedef std::map<std::string, T> map;
|
||||
typedef typename map::iterator iterator;
|
||||
typedef typename map::const_iterator const_iterator;
|
||||
|
||||
Map() : m_default() { }
|
||||
|
||||
iterator begin() { return m_map.begin(); }
|
||||
iterator end() { return m_map.end(); }
|
||||
|
||||
const_iterator begin() const { return m_map.begin(); }
|
||||
const_iterator end() const { return m_map.end(); }
|
||||
|
||||
const T& operator[](const std::string& name) const {
|
||||
const_iterator it = m_map.find(name);
|
||||
if (it != m_map.end())
|
||||
return it->second;
|
||||
else
|
||||
return m_default;
|
||||
}
|
||||
|
||||
T& operator[](const std::string& name) {
|
||||
iterator it = m_map.find(name);
|
||||
if (it != m_map.end())
|
||||
return it->second;
|
||||
else
|
||||
return m_map[name] = T();
|
||||
}
|
||||
|
||||
void add(const std::string& name, T value) {
|
||||
m_map[name] = value;
|
||||
}
|
||||
|
||||
bool exists(const std::string& name) const {
|
||||
return (m_map.find(name) != m_map.end());
|
||||
}
|
||||
|
||||
private:
|
||||
map m_map;
|
||||
T m_default;
|
||||
};
|
||||
|
||||
} // namespace css
|
||||
|
||||
#endif
|
29
src/css/query.cpp
Normal file
29
src/css/query.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "css/query.h"
|
||||
|
||||
namespace css {
|
||||
|
||||
void Query::addFromStyle(const Style* style)
|
||||
{
|
||||
for (Style::const_iterator it = style->begin(), end = style->end();
|
||||
it != end; ++it) {
|
||||
addRuleValue(it->first, style);
|
||||
}
|
||||
}
|
||||
|
||||
void Query::addRuleValue(const std::string& ruleName, const Style* style)
|
||||
{
|
||||
if (!m_ruleValue.exists(ruleName))
|
||||
m_ruleValue.add(ruleName, style);
|
||||
}
|
||||
|
||||
} // namespace css
|
43
src/css/query.h
Normal file
43
src/css/query.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifndef CSS_QUERY_H_INCLUDED
|
||||
#define CSS_QUERY_H_INCLUDED
|
||||
|
||||
#include "css/rule.h"
|
||||
#include "css/style.h"
|
||||
#include "css/value.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace css {
|
||||
|
||||
class Query {
|
||||
public:
|
||||
Query() { }
|
||||
|
||||
// Adds more rules from the given style only if the query doesn't
|
||||
// contain those rules already.
|
||||
void addFromStyle(const Style* style);
|
||||
|
||||
const Value& operator[](const Rule& rule) const {
|
||||
const Style* style = m_ruleValue[rule.name()];
|
||||
if (style)
|
||||
return (*style)[rule.name()];
|
||||
else
|
||||
return m_none;
|
||||
}
|
||||
|
||||
private:
|
||||
void addRuleValue(const std::string& ruleName, const Style* style);
|
||||
|
||||
Styles m_ruleValue;
|
||||
Value m_none;
|
||||
};
|
||||
|
||||
} // namespace css
|
||||
|
||||
#endif
|
20
src/css/rule.cpp
Normal file
20
src/css/rule.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "css/rule.h"
|
||||
|
||||
namespace css {
|
||||
|
||||
Rule::Rule(const std::string& name) :
|
||||
m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace css
|
32
src/css/rule.h
Normal file
32
src/css/rule.h
Normal file
@ -0,0 +1,32 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifndef CSS_RULE_H_INCLUDED
|
||||
#define CSS_RULE_H_INCLUDED
|
||||
|
||||
#include "css/map.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace css {
|
||||
|
||||
class Rule {
|
||||
public:
|
||||
Rule() { }
|
||||
Rule(const std::string& name);
|
||||
|
||||
const std::string& name() const { return m_name; }
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
typedef Map<Rule*> Rules;
|
||||
|
||||
} // namespace css
|
||||
|
||||
#endif
|
110
src/css/sheet.cpp
Normal file
110
src/css/sheet.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "css/sheet.h"
|
||||
|
||||
#include "css/compound_style.h"
|
||||
#include "css/query.h"
|
||||
#include "css/stateful_style.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace css {
|
||||
|
||||
Sheet::Sheet()
|
||||
{
|
||||
}
|
||||
|
||||
void Sheet::addRule(Rule* rule)
|
||||
{
|
||||
m_rules.add(rule->name(), rule);
|
||||
}
|
||||
|
||||
void Sheet::addStyle(Style* style)
|
||||
{
|
||||
m_styles.add(style->name(), style);
|
||||
}
|
||||
|
||||
const Style* Sheet::getStyle(const std::string& name)
|
||||
{
|
||||
return m_styles[name];
|
||||
}
|
||||
|
||||
Query Sheet::query(const StatefulStyle& compound)
|
||||
{
|
||||
const Style* firstStyle = &compound.style();
|
||||
const Style* style;
|
||||
Query query;
|
||||
std::string name;
|
||||
|
||||
// We create a string with all states. This is the style with
|
||||
// highest priority.
|
||||
std::string states;
|
||||
for (States::const_iterator
|
||||
state_it = compound.states().begin(),
|
||||
state_end = compound.states().end(); state_it != state_end; ++state_it) {
|
||||
states += StatefulStyle::kSeparator;
|
||||
states += (*state_it)->name();
|
||||
}
|
||||
|
||||
// Query by priority for the following styles:
|
||||
// style:state1:state2:...
|
||||
// ...
|
||||
// base1:state1:state2:...
|
||||
// base0:state1:state2:...
|
||||
for (style=firstStyle; style != NULL; style=style->base()) {
|
||||
name = style->name();
|
||||
name += states;
|
||||
|
||||
const Style* style2 = m_styles[name];
|
||||
if (style2)
|
||||
query.addFromStyle(style2);
|
||||
}
|
||||
|
||||
// Query for:
|
||||
// style:state2
|
||||
// style:state1
|
||||
// ...
|
||||
// base1:state2
|
||||
// base1:state1
|
||||
// base0:state2
|
||||
// base0:state1
|
||||
for (States::const_reverse_iterator
|
||||
state_it = compound.states().rbegin(),
|
||||
state_end = compound.states().rend(); state_it != state_end; ++state_it) {
|
||||
for (style=firstStyle; style != NULL; style=style->base()) {
|
||||
name = style->name();
|
||||
name += StatefulStyle::kSeparator;
|
||||
name += (*state_it)->name();
|
||||
|
||||
const Style* style2 = m_styles[name];
|
||||
if (style2)
|
||||
query.addFromStyle(style2);
|
||||
}
|
||||
}
|
||||
|
||||
// Query for:
|
||||
// style
|
||||
// ...
|
||||
// base1
|
||||
// base0
|
||||
for (style=firstStyle; style != NULL; style=style->base()) {
|
||||
query.addFromStyle(style);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
CompoundStyle Sheet::compoundStyle(const std::string& name)
|
||||
{
|
||||
return CompoundStyle(this, name);
|
||||
}
|
||||
|
||||
} // namespace css
|
42
src/css/sheet.h
Normal file
42
src/css/sheet.h
Normal file
@ -0,0 +1,42 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifndef CSS_SHEET_H_INCLUDED
|
||||
#define CSS_SHEET_H_INCLUDED
|
||||
|
||||
#include "css/rule.h"
|
||||
#include "css/style.h"
|
||||
#include "css/value.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace css {
|
||||
|
||||
class CompoundStyle;
|
||||
class Query;
|
||||
class StatefulStyle;
|
||||
|
||||
class Sheet {
|
||||
public:
|
||||
Sheet();
|
||||
|
||||
void addRule(Rule* rule);
|
||||
void addStyle(Style* style);
|
||||
|
||||
const Style* getStyle(const std::string& name);
|
||||
|
||||
Query query(const StatefulStyle& stateful);
|
||||
CompoundStyle compoundStyle(const std::string& name);
|
||||
|
||||
private:
|
||||
Rules m_rules;
|
||||
Styles m_styles;
|
||||
};
|
||||
|
||||
} // namespace css
|
||||
|
||||
#endif
|
76
src/css/state.h
Normal file
76
src/css/state.h
Normal file
@ -0,0 +1,76 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifndef CSS_STATE_H_INCLUDED
|
||||
#define CSS_STATE_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace css {
|
||||
|
||||
class State {
|
||||
public:
|
||||
State() { }
|
||||
State(const std::string& name) : m_name(name) { }
|
||||
|
||||
const std::string& name() const { return m_name; }
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
class States {
|
||||
public:
|
||||
typedef std::vector<const State*> List;
|
||||
typedef List::iterator iterator;
|
||||
typedef List::const_iterator const_iterator;
|
||||
typedef List::reverse_iterator reverse_iterator;
|
||||
typedef List::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
States() { }
|
||||
States(const State& state) {
|
||||
operator+=(state);
|
||||
}
|
||||
|
||||
iterator begin() { return m_list.begin(); }
|
||||
iterator end() { return m_list.end(); }
|
||||
const_iterator begin() const { return m_list.begin(); }
|
||||
const_iterator end() const { return m_list.end(); }
|
||||
reverse_iterator rbegin() { return m_list.rbegin(); }
|
||||
reverse_iterator rend() { return m_list.rend(); }
|
||||
const_reverse_iterator rbegin() const { return m_list.rbegin(); }
|
||||
const_reverse_iterator rend() const { return m_list.rend(); }
|
||||
|
||||
States& operator+=(const State& other) {
|
||||
m_list.push_back(&other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
States& operator+=(const States& others) {
|
||||
for (const_iterator it=others.begin(), end=others.end(); it != end; ++it)
|
||||
operator+=(*(*it));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator<(const States& other) const {
|
||||
return m_list < other.m_list;
|
||||
}
|
||||
|
||||
private:
|
||||
List m_list;
|
||||
};
|
||||
|
||||
inline States operator+(const State& a, const State& b) {
|
||||
States states;
|
||||
states += a;
|
||||
states += b;
|
||||
return states;
|
||||
}
|
||||
|
||||
} // namespace css
|
||||
|
||||
#endif
|
73
src/css/stateful_style.h
Normal file
73
src/css/stateful_style.h
Normal file
@ -0,0 +1,73 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifndef CSS_STATEFUL_STYLE_H_INCLUDED
|
||||
#define CSS_STATEFUL_STYLE_H_INCLUDED
|
||||
|
||||
#include "css/rule.h"
|
||||
#include "css/state.h"
|
||||
#include "css/style.h"
|
||||
#include "css/value.h"
|
||||
|
||||
namespace css {
|
||||
|
||||
class StatefulStyle {
|
||||
public:
|
||||
static const char kSeparator = ':';
|
||||
|
||||
StatefulStyle() : m_style(NULL) { }
|
||||
StatefulStyle(const Style& style) : m_style(&style) { }
|
||||
StatefulStyle(const State& state) {
|
||||
operator+=(state);
|
||||
}
|
||||
StatefulStyle(const Style& style, const States& states) :
|
||||
m_style(&style) {
|
||||
operator+=(states);
|
||||
}
|
||||
|
||||
const Style& style() const { return *m_style; }
|
||||
const States& states() const { return m_states; }
|
||||
|
||||
StatefulStyle& setStyle(const Style& style) {
|
||||
m_style = &style;
|
||||
return *this;
|
||||
}
|
||||
StatefulStyle& operator+=(const State& state) {
|
||||
m_states += state;
|
||||
return *this;
|
||||
}
|
||||
StatefulStyle& operator+=(const States& states) {
|
||||
m_states += states;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const Style* m_style;
|
||||
States m_states;
|
||||
};
|
||||
|
||||
inline StatefulStyle operator+(const Style& style, const State& state) {
|
||||
StatefulStyle styleState;
|
||||
styleState.setStyle(style);
|
||||
styleState += state;
|
||||
return styleState;
|
||||
}
|
||||
|
||||
inline StatefulStyle operator+(StatefulStyle& styleState, const State& state) {
|
||||
StatefulStyle styleState2 = styleState;
|
||||
styleState2 += state;
|
||||
return styleState2;
|
||||
}
|
||||
|
||||
inline StatefulStyle operator+(StatefulStyle& styleState, const States& states) {
|
||||
StatefulStyle styleState2 = styleState;
|
||||
styleState2 += states;
|
||||
return styleState2;
|
||||
}
|
||||
|
||||
} // namespace css
|
||||
|
||||
#endif
|
20
src/css/style.cpp
Normal file
20
src/css/style.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "css/style.h"
|
||||
|
||||
namespace css {
|
||||
|
||||
Style::Style(const std::string& name, const Style* base) :
|
||||
m_name(name),
|
||||
m_base(base) {
|
||||
}
|
||||
|
||||
} // namespace css
|
53
src/css/style.h
Normal file
53
src/css/style.h
Normal file
@ -0,0 +1,53 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifndef CSS_STYLE_H_INCLUDED
|
||||
#define CSS_STYLE_H_INCLUDED
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "css/map.h"
|
||||
#include "css/rule.h"
|
||||
#include "css/value.h"
|
||||
|
||||
namespace css {
|
||||
|
||||
class Style {
|
||||
public:
|
||||
typedef Values::iterator iterator;
|
||||
typedef Values::const_iterator const_iterator;
|
||||
|
||||
Style() { }
|
||||
Style(const std::string& name, const Style* base = NULL);
|
||||
|
||||
const std::string& name() const { return m_name; }
|
||||
const Style* base() const { return m_base; }
|
||||
|
||||
const Value& operator[](const Rule& rule) const {
|
||||
return m_values[rule.name()];
|
||||
}
|
||||
|
||||
Value& operator[](const Rule& rule) {
|
||||
return m_values[rule.name()];
|
||||
}
|
||||
|
||||
iterator begin() { return m_values.begin(); }
|
||||
iterator end() { return m_values.end(); }
|
||||
const_iterator begin() const { return m_values.begin(); }
|
||||
const_iterator end() const { return m_values.end(); }
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
const Style* m_base;
|
||||
Values m_values;
|
||||
};
|
||||
|
||||
typedef Map<const Style*> Styles;
|
||||
|
||||
} // namespace css
|
||||
|
||||
#endif
|
98
src/css/value.cpp
Normal file
98
src/css/value.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "css/value.h"
|
||||
|
||||
namespace css {
|
||||
|
||||
Value::Value() :
|
||||
m_type(None)
|
||||
{
|
||||
}
|
||||
|
||||
Value::Value(double value, const std::string& unit) :
|
||||
m_type(Number),
|
||||
m_number(value),
|
||||
m_string(unit)
|
||||
{
|
||||
}
|
||||
|
||||
Value::Value(const std::string& value) :
|
||||
m_type(String),
|
||||
m_string(value)
|
||||
{
|
||||
}
|
||||
|
||||
double Value::number() const
|
||||
{
|
||||
if (m_type == Number)
|
||||
return m_number;
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
std::string Value::string() const
|
||||
{
|
||||
if (m_type == String)
|
||||
return m_string;
|
||||
else
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string Value::unit() const
|
||||
{
|
||||
if (m_type == Number)
|
||||
return m_string;
|
||||
else
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void Value::setNumber(double value)
|
||||
{
|
||||
if (m_type != Number) {
|
||||
m_type = Number;
|
||||
m_string = "";
|
||||
}
|
||||
m_number = value;
|
||||
}
|
||||
|
||||
void Value::setString(const std::string& value)
|
||||
{
|
||||
m_type = String;
|
||||
m_string = value;
|
||||
}
|
||||
|
||||
void Value::setUnit(const std::string& unit)
|
||||
{
|
||||
if (m_type != Number) {
|
||||
m_type = Number;
|
||||
m_number = 0.0;
|
||||
}
|
||||
m_string = unit;
|
||||
}
|
||||
|
||||
bool Value::operator==(const Value& other) const
|
||||
{
|
||||
if (m_type != other.m_type)
|
||||
return false;
|
||||
|
||||
switch (m_type) {
|
||||
case None:
|
||||
return true;
|
||||
case Number:
|
||||
return m_number == other.m_number && m_string == other.m_string;
|
||||
case String:
|
||||
return m_string == other.m_string;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace css
|
53
src/css/value.h
Normal file
53
src/css/value.h
Normal file
@ -0,0 +1,53 @@
|
||||
// Aseprite CSS Library
|
||||
// Copyright (C) 2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifndef CSS_VALUE_H_INCLUDED
|
||||
#define CSS_VALUE_H_INCLUDED
|
||||
|
||||
#include "css/map.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace css {
|
||||
|
||||
class Value {
|
||||
public:
|
||||
enum Type {
|
||||
None,
|
||||
Number,
|
||||
String
|
||||
};
|
||||
|
||||
Value();
|
||||
explicit Value(double value, const std::string& unit = "");
|
||||
explicit Value(const std::string& value);
|
||||
|
||||
Type type() const { return m_type; }
|
||||
|
||||
double number() const;
|
||||
std::string string() const;
|
||||
std::string unit() const;
|
||||
|
||||
void setNumber(double value);
|
||||
void setString(const std::string& value);
|
||||
void setUnit(const std::string& unit = "");
|
||||
|
||||
bool operator==(const Value& other) const;
|
||||
bool operator!=(const Value& other) const {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
double m_number;
|
||||
std::string m_string;
|
||||
};
|
||||
|
||||
typedef Map<Value> Values;
|
||||
|
||||
} // namespace css
|
||||
|
||||
#endif
|
@ -145,13 +145,21 @@ gfx::Size Graphics::fitString(const std::string& str, int maxWidth, int align)
|
||||
|
||||
gfx::Size Graphics::drawStringAlgorithm(const std::string& str, Color fg, Color bg, const gfx::Rect& rc, int align, bool draw)
|
||||
{
|
||||
gfx::Point pt(0, rc.y);
|
||||
|
||||
if ((align & (JI_MIDDLE | JI_BOTTOM)) != 0) {
|
||||
gfx::Size preSize = drawStringAlgorithm(str, ColorNone, ColorNone, rc, 0, false);
|
||||
if (align & JI_MIDDLE)
|
||||
pt.y = rc.y + rc.h/2 - preSize.h/2;
|
||||
else if (align & JI_BOTTOM)
|
||||
pt.y = rc.y + rc.h - preSize.h;
|
||||
}
|
||||
|
||||
gfx::Size calculatedSize(0, 0);
|
||||
size_t beg, end, new_word_beg, old_end;
|
||||
std::string line;
|
||||
gfx::Point pt;
|
||||
|
||||
// Draw line-by-line
|
||||
pt.y = rc.y;
|
||||
for (beg=end=0; end != std::string::npos; ) {
|
||||
pt.x = rc.x;
|
||||
|
||||
@ -209,19 +217,19 @@ gfx::Size Graphics::drawStringAlgorithm(const std::string& str, Color fg, Color
|
||||
ji_font_set_aa_mode(m_currentFont, to_system(bg));
|
||||
textout_ex(m_bmp, m_currentFont, line.c_str(), m_dx+xout, m_dy+pt.y, to_system(fg), to_system(bg));
|
||||
|
||||
jrectexclude(m_bmp,
|
||||
m_dx+rc.x, m_dy+pt.y, m_dx+rc.x+rc.w-1, m_dy+pt.y+lineSize.h-1,
|
||||
m_dx+xout, m_dy+pt.y, m_dx+xout+lineSize.w-1, m_dy+pt.y+lineSize.h-1, bg);
|
||||
if (!is_transparent(bg))
|
||||
jrectexclude(m_bmp,
|
||||
m_dx+rc.x, m_dy+pt.y, m_dx+rc.x+rc.w-1, m_dy+pt.y+lineSize.h-1,
|
||||
m_dx+xout, m_dy+pt.y, m_dx+xout+lineSize.w-1, m_dy+pt.y+lineSize.h-1, bg);
|
||||
}
|
||||
|
||||
pt.y += lineSize.h;
|
||||
calculatedSize.h += lineSize.h;
|
||||
beg = end+1;
|
||||
}
|
||||
|
||||
calculatedSize.h += pt.y;
|
||||
|
||||
// Fill bottom area
|
||||
if (draw) {
|
||||
if (draw && !is_transparent(bg)) {
|
||||
if (pt.y < rc.y+rc.h)
|
||||
fillRect(bg, gfx::Rect(rc.x, pt.y, rc.w, rc.y+rc.h-pt.y));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user