mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-18 11:42:47 +00:00
Add close/modified icon to tabs
This commit is contained in:
parent
13611eb23e
commit
f4e01345c6
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@ -6,6 +6,9 @@
|
|||||||
<dimensions>
|
<dimensions>
|
||||||
<dim id="tabs_height" value="17" />
|
<dim id="tabs_height" value="17" />
|
||||||
<dim id="tabs_empty_height" value="5" />
|
<dim id="tabs_empty_height" value="5" />
|
||||||
|
<dim id="tabs_width" value="80" />
|
||||||
|
<dim id="tabs_close_icon_width" value="14" />
|
||||||
|
<dim id="tabs_close_icon_height" value="12" />
|
||||||
</dimensions>
|
</dimensions>
|
||||||
|
|
||||||
<colors>
|
<colors>
|
||||||
@ -224,8 +227,14 @@
|
|||||||
<part id="tab_bottom_active" x="16" y="124" w1="4" w2="7" w3="5" h1="2" h2="1" h3="2" />
|
<part id="tab_bottom_active" x="16" y="124" w1="4" w2="7" w3="5" h1="2" h2="1" h3="2" />
|
||||||
<part id="tab_bottom_normal" x="2" y="124" w="12" h="5" />
|
<part id="tab_bottom_normal" x="2" y="124" w="12" h="5" />
|
||||||
<part id="tab_filler" x="0" y="112" w="2" h="12" />
|
<part id="tab_filler" x="0" y="112" w="2" h="12" />
|
||||||
<part id="editor_normal" x="32" y="112" w1="3" w2="10" w3="3" h1="3" h2="10" h3="3" />
|
<part id="tab_modified_icon_normal" x="32" y="112" w="5" h="5" />
|
||||||
<part id="editor_selected" x="48" y="112" w1="3" w2="10" w3="3" h1="3" h2="10" h3="3" />
|
<part id="tab_modified_icon_active" x="32" y="117" w="5" h="5" />
|
||||||
|
<part id="tab_close_icon_normal" x="37" y="112" w="5" h="5" />
|
||||||
|
<part id="tab_close_icon_active" x="37" y="117" w="5" h="5" />
|
||||||
|
<part id="tab_icon_bg_active" x="42" y="112" w="14" h="12" />
|
||||||
|
<part id="tab_icon_bg_hover" x="56" y="112" w="14" h="12" />
|
||||||
|
<part id="editor_normal" x="40" y="96" w1="3" w2="10" w3="3" h1="3" h2="10" h3="3" />
|
||||||
|
<part id="editor_selected" x="56" y="96" w1="3" w2="10" w3="3" h1="3" h2="10" h3="3" />
|
||||||
<part id="colorbar_0" x="0" y="192" w1="5" w2="6" w3="5" h1="5" h2="6" h3="5" />
|
<part id="colorbar_0" x="0" y="192" w1="5" w2="6" w3="5" h1="5" h2="6" h3="5" />
|
||||||
<part id="colorbar_1" x="16" y="192" w1="5" w2="6" w3="5" h1="5" h2="6" h3="5" />
|
<part id="colorbar_1" x="16" y="192" w1="5" w2="6" w3="5" h1="5" h2="6" h3="5" />
|
||||||
<part id="colorbar_2" x="0" y="208" w1="5" w2="6" w3="5" h1="5" h2="6" h3="5" />
|
<part id="colorbar_2" x="0" y="208" w1="5" w2="6" w3="5" h1="5" h2="6" h3="5" />
|
||||||
@ -617,16 +626,59 @@
|
|||||||
<background part="tab_active" color="tab_active_face" />
|
<background part="tab_active" color="tab_active_face" />
|
||||||
<text color="tab_active_text" />
|
<text color="tab_active_text" />
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- tab_bottom -->
|
||||||
<style id="tab_bottom">
|
<style id="tab_bottom">
|
||||||
<background part="tab_bottom_normal" color="tab_normal_face" repeat="repeat-x" />
|
<background part="tab_bottom_normal" color="tab_normal_face" repeat="repeat-x" />
|
||||||
</style>
|
</style>
|
||||||
<style id="tab_bottom:active">
|
<style id="tab_bottom:active">
|
||||||
<background part="tab_bottom_active" color="tab_active_face" />
|
<background part="tab_bottom_active" color="tab_active_face" />
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- tab_filler -->
|
||||||
<style id="tab_filler">
|
<style id="tab_filler">
|
||||||
<background part="tab_filler" color="window_face" repeat="repeat-x" />
|
<background part="tab_filler" color="window_face" repeat="repeat-x" />
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- tab_icon -->
|
||||||
|
<style id="tab_icon">
|
||||||
|
<icon align="left" valign="middle" x="3" />
|
||||||
|
</style>
|
||||||
|
<style id="tab_icon:hover">
|
||||||
|
<background part="tab_icon_bg_hover" />
|
||||||
|
</style>
|
||||||
|
<style id="tab_icon:clicked">
|
||||||
|
<background part="tab_icon_bg_active" />
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- tab_close_icon -->
|
||||||
|
<style id="tab_close_icon" base="tab_icon">
|
||||||
|
<icon part="tab_close_icon_normal" />
|
||||||
|
</style>
|
||||||
|
<style id="tab_close_icon:hover">
|
||||||
|
<icon part="tab_close_icon_normal" />
|
||||||
|
</style>
|
||||||
|
<style id="tab_close_icon:active">
|
||||||
|
<icon part="tab_close_icon_active" />
|
||||||
|
</style>
|
||||||
|
<style id="tab_close_icon:clicked">
|
||||||
|
<icon part="tab_close_icon_normal" />
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- tab_modified_icon -->
|
||||||
|
<style id="tab_modified_icon" base="tab_icon">
|
||||||
|
<icon part="tab_modified_icon_normal" />
|
||||||
|
</style>
|
||||||
|
<style id="tab_modified_icon:hover">
|
||||||
|
<icon part="tab_modified_icon_normal" />
|
||||||
|
</style>
|
||||||
|
<style id="tab_modified_icon:active">
|
||||||
|
<icon part="tab_modified_icon_active" />
|
||||||
|
</style>
|
||||||
|
<style id="tab_modified_icon:clicked">
|
||||||
|
<icon part="tab_modified_icon_normal" />
|
||||||
|
</style>
|
||||||
|
|
||||||
</stylesheet>
|
</stylesheet>
|
||||||
|
|
||||||
</skin>
|
</skin>
|
||||||
|
@ -191,13 +191,7 @@ void DocumentView::getDocumentLocation(DocumentLocation* location) const
|
|||||||
|
|
||||||
std::string DocumentView::getTabText()
|
std::string DocumentView::getTabText()
|
||||||
{
|
{
|
||||||
std::string str = m_document->name();
|
return m_document->name();
|
||||||
|
|
||||||
// Add an asterisk if the document is modified.
|
|
||||||
if (m_document->isModified())
|
|
||||||
str += "*";
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkspaceView* DocumentView::cloneWorkspaceView()
|
WorkspaceView* DocumentView::cloneWorkspaceView()
|
||||||
|
@ -294,6 +294,22 @@ void MainWindow::clickTab(Tabs* tabs, TabView* tabView, ui::MouseButtons buttons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::clickClose(Tabs* tabs, TabView* tabView)
|
||||||
|
{
|
||||||
|
DocumentView* docView = dynamic_cast<DocumentView*>(tabView);
|
||||||
|
if (!docView)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UIContext* context = UIContext::instance();
|
||||||
|
context->setActiveView(docView);
|
||||||
|
context->updateFlags();
|
||||||
|
|
||||||
|
Command* close_file_cmd =
|
||||||
|
CommandsModule::instance()->getCommandByName(CommandId::CloseFile);
|
||||||
|
|
||||||
|
context->executeCommand(close_file_cmd, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::mouseOverTab(Tabs* tabs, TabView* tabView)
|
void MainWindow::mouseOverTab(Tabs* tabs, TabView* tabView)
|
||||||
{
|
{
|
||||||
// Note: tabView can be NULL
|
// Note: tabView can be NULL
|
||||||
@ -307,4 +323,15 @@ void MainWindow::mouseOverTab(Tabs* tabs, TabView* tabView)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MainWindow::isModified(Tabs* tabs, TabView* tabView)
|
||||||
|
{
|
||||||
|
if (DocumentView* docView = dynamic_cast<DocumentView*>(tabView)) {
|
||||||
|
Document* document = docView->getDocument();
|
||||||
|
return document->isModified();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -61,8 +61,10 @@ namespace app {
|
|||||||
void popTimeline();
|
void popTimeline();
|
||||||
|
|
||||||
// TabsDelegate implementation.
|
// TabsDelegate implementation.
|
||||||
void clickTab(Tabs* tabs, TabView* tabView, ui::MouseButtons buttons);
|
void clickTab(Tabs* tabs, TabView* tabView, ui::MouseButtons buttons) override;
|
||||||
void mouseOverTab(Tabs* tabs, TabView* tabView);
|
void clickClose(Tabs* tabs, TabView* tabView) override;
|
||||||
|
void mouseOverTab(Tabs* tabs, TabView* tabView) override;
|
||||||
|
bool isModified(Tabs* tabs, TabView* tabView) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool onProcessMessage(ui::Message* msg) override;
|
bool onProcessMessage(ui::Message* msg) override;
|
||||||
|
@ -583,20 +583,26 @@ void SkinTheme::onRegenerate()
|
|||||||
else if (ruleName == "icon") {
|
else if (ruleName == "icon") {
|
||||||
if (align) (*style)[StyleSheet::iconAlignRule()] = css::Value(align);
|
if (align) (*style)[StyleSheet::iconAlignRule()] = css::Value(align);
|
||||||
if (part_id) (*style)[StyleSheet::iconPartRule()] = css::Value(part_id);
|
if (part_id) (*style)[StyleSheet::iconPartRule()] = css::Value(part_id);
|
||||||
|
|
||||||
|
const char* x = xmlRule->Attribute("x");
|
||||||
|
const char* y = xmlRule->Attribute("y");
|
||||||
|
|
||||||
|
if (x) (*style)[StyleSheet::iconXRule()] = css::Value(strtol(x, NULL, 10));
|
||||||
|
if (y) (*style)[StyleSheet::iconYRule()] = css::Value(strtol(y, NULL, 10));
|
||||||
}
|
}
|
||||||
else if (ruleName == "text") {
|
else if (ruleName == "text") {
|
||||||
if (color_id) (*style)[StyleSheet::textColorRule()] = css::Value(color_id);
|
if (color_id) (*style)[StyleSheet::textColorRule()] = css::Value(color_id);
|
||||||
if (align) (*style)[StyleSheet::textAlignRule()] = css::Value(align);
|
if (align) (*style)[StyleSheet::textAlignRule()] = css::Value(align);
|
||||||
|
|
||||||
const char* padding_left = xmlRule->Attribute("padding-left");
|
const char* l = xmlRule->Attribute("padding-left");
|
||||||
const char* padding_top = xmlRule->Attribute("padding-top");
|
const char* t = xmlRule->Attribute("padding-top");
|
||||||
const char* padding_right = xmlRule->Attribute("padding-right");
|
const char* r = xmlRule->Attribute("padding-right");
|
||||||
const char* padding_bottom = xmlRule->Attribute("padding-bottom");
|
const char* b = xmlRule->Attribute("padding-bottom");
|
||||||
|
|
||||||
if (padding_left) (*style)[StyleSheet::paddingLeftRule()] = css::Value(strtol(padding_left, NULL, 10));
|
if (l) (*style)[StyleSheet::paddingLeftRule()] = css::Value(strtol(l, NULL, 10));
|
||||||
if (padding_top) (*style)[StyleSheet::paddingTopRule()] = css::Value(strtol(padding_top, NULL, 10));
|
if (t) (*style)[StyleSheet::paddingTopRule()] = css::Value(strtol(t, NULL, 10));
|
||||||
if (padding_right) (*style)[StyleSheet::paddingRightRule()] = css::Value(strtol(padding_right, NULL, 10));
|
if (r) (*style)[StyleSheet::paddingRightRule()] = css::Value(strtol(r, NULL, 10));
|
||||||
if (padding_bottom) (*style)[StyleSheet::paddingBottomRule()] = css::Value(strtol(padding_bottom, NULL, 10));
|
if (b) (*style)[StyleSheet::paddingBottomRule()] = css::Value(strtol(b, NULL, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlRule = xmlRule->NextSiblingElement();
|
xmlRule = xmlRule->NextSiblingElement();
|
||||||
|
@ -107,6 +107,9 @@ void IconRule::onPaint(ui::Graphics* g, const gfx::Rect& bounds, const char* tex
|
|||||||
else
|
else
|
||||||
y = bounds.y;
|
y = bounds.y;
|
||||||
|
|
||||||
|
x += m_x;
|
||||||
|
y += m_y;
|
||||||
|
|
||||||
g->drawRgbaSurface(bmp, x, y);
|
g->drawRgbaSurface(bmp, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,6 +123,8 @@ Rules::Rules(const css::Query& query) :
|
|||||||
css::Value backgroundRepeat = query[StyleSheet::backgroundRepeatRule()];
|
css::Value backgroundRepeat = query[StyleSheet::backgroundRepeatRule()];
|
||||||
css::Value iconAlign = query[StyleSheet::iconAlignRule()];
|
css::Value iconAlign = query[StyleSheet::iconAlignRule()];
|
||||||
css::Value iconPart = query[StyleSheet::iconPartRule()];
|
css::Value iconPart = query[StyleSheet::iconPartRule()];
|
||||||
|
css::Value iconX = query[StyleSheet::iconXRule()];
|
||||||
|
css::Value iconY = query[StyleSheet::iconYRule()];
|
||||||
css::Value textAlign = query[StyleSheet::textAlignRule()];
|
css::Value textAlign = query[StyleSheet::textAlignRule()];
|
||||||
css::Value textColor = query[StyleSheet::textColorRule()];
|
css::Value textColor = query[StyleSheet::textColorRule()];
|
||||||
css::Value paddingLeft = query[StyleSheet::paddingLeftRule()];
|
css::Value paddingLeft = query[StyleSheet::paddingLeftRule()];
|
||||||
@ -138,10 +143,14 @@ Rules::Rules(const css::Query& query) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (iconAlign != none
|
if (iconAlign != none
|
||||||
|| iconPart != none) {
|
|| iconPart != none
|
||||||
|
|| iconX != none
|
||||||
|
|| iconY != none) {
|
||||||
m_icon = new IconRule();
|
m_icon = new IconRule();
|
||||||
m_icon->setAlign((int)iconAlign.number());
|
m_icon->setAlign((int)iconAlign.number());
|
||||||
m_icon->setPart(StyleSheet::convertPart(iconPart));
|
m_icon->setPart(StyleSheet::convertPart(iconPart));
|
||||||
|
m_icon->setX((int)iconX.number()*ui::guiscale());
|
||||||
|
m_icon->setY((int)iconY.number()*ui::guiscale());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textAlign != none
|
if (textAlign != none
|
||||||
|
@ -85,6 +85,8 @@ namespace app {
|
|||||||
|
|
||||||
void setAlign(int align) { m_align = align; }
|
void setAlign(int align) { m_align = align; }
|
||||||
void setPart(const SkinPartPtr& part) { m_part = part; }
|
void setPart(const SkinPartPtr& part) { m_part = part; }
|
||||||
|
void setX(int x) { m_x = x; }
|
||||||
|
void setY(int y) { m_y = y; }
|
||||||
|
|
||||||
SkinPartPtr getPart() { return m_part; }
|
SkinPartPtr getPart() { return m_part; }
|
||||||
|
|
||||||
@ -94,6 +96,7 @@ namespace app {
|
|||||||
private:
|
private:
|
||||||
int m_align;
|
int m_align;
|
||||||
SkinPartPtr m_part;
|
SkinPartPtr m_part;
|
||||||
|
int m_x, m_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Rules {
|
class Rules {
|
||||||
|
@ -26,6 +26,8 @@ css::Rule StyleSheet::m_backgroundPartRule("background-part");
|
|||||||
css::Rule StyleSheet::m_backgroundRepeatRule("background-repeat");
|
css::Rule StyleSheet::m_backgroundRepeatRule("background-repeat");
|
||||||
css::Rule StyleSheet::m_iconAlignRule("icon-align");
|
css::Rule StyleSheet::m_iconAlignRule("icon-align");
|
||||||
css::Rule StyleSheet::m_iconPartRule("icon-part");
|
css::Rule StyleSheet::m_iconPartRule("icon-part");
|
||||||
|
css::Rule StyleSheet::m_iconXRule("icon-x");
|
||||||
|
css::Rule StyleSheet::m_iconYRule("icon-y");
|
||||||
css::Rule StyleSheet::m_textAlignRule("text-align");
|
css::Rule StyleSheet::m_textAlignRule("text-align");
|
||||||
css::Rule StyleSheet::m_textColorRule("text-color");
|
css::Rule StyleSheet::m_textColorRule("text-color");
|
||||||
css::Rule StyleSheet::m_paddingLeftRule("padding-left");
|
css::Rule StyleSheet::m_paddingLeftRule("padding-left");
|
||||||
@ -41,6 +43,8 @@ StyleSheet::StyleSheet()
|
|||||||
m_sheet->addRule(&m_backgroundRepeatRule);
|
m_sheet->addRule(&m_backgroundRepeatRule);
|
||||||
m_sheet->addRule(&m_iconAlignRule);
|
m_sheet->addRule(&m_iconAlignRule);
|
||||||
m_sheet->addRule(&m_iconPartRule);
|
m_sheet->addRule(&m_iconPartRule);
|
||||||
|
m_sheet->addRule(&m_iconXRule);
|
||||||
|
m_sheet->addRule(&m_iconYRule);
|
||||||
m_sheet->addRule(&m_textAlignRule);
|
m_sheet->addRule(&m_textAlignRule);
|
||||||
m_sheet->addRule(&m_textColorRule);
|
m_sheet->addRule(&m_textColorRule);
|
||||||
m_sheet->addRule(&m_paddingLeftRule);
|
m_sheet->addRule(&m_paddingLeftRule);
|
||||||
|
@ -41,6 +41,8 @@ namespace app {
|
|||||||
static css::Rule& backgroundRepeatRule() { return m_backgroundRepeatRule; }
|
static css::Rule& backgroundRepeatRule() { return m_backgroundRepeatRule; }
|
||||||
static css::Rule& iconAlignRule() { return m_iconAlignRule; }
|
static css::Rule& iconAlignRule() { return m_iconAlignRule; }
|
||||||
static css::Rule& iconPartRule() { return m_iconPartRule; }
|
static css::Rule& iconPartRule() { return m_iconPartRule; }
|
||||||
|
static css::Rule& iconXRule() { return m_iconXRule; }
|
||||||
|
static css::Rule& iconYRule() { return m_iconYRule; }
|
||||||
static css::Rule& textAlignRule() { return m_textAlignRule; }
|
static css::Rule& textAlignRule() { return m_textAlignRule; }
|
||||||
static css::Rule& textColorRule() { return m_textColorRule; }
|
static css::Rule& textColorRule() { return m_textColorRule; }
|
||||||
static css::Rule& paddingLeftRule() { return m_paddingLeftRule; }
|
static css::Rule& paddingLeftRule() { return m_paddingLeftRule; }
|
||||||
@ -65,6 +67,8 @@ namespace app {
|
|||||||
static css::Rule m_backgroundRepeatRule;
|
static css::Rule m_backgroundRepeatRule;
|
||||||
static css::Rule m_iconAlignRule;
|
static css::Rule m_iconAlignRule;
|
||||||
static css::Rule m_iconPartRule;
|
static css::Rule m_iconPartRule;
|
||||||
|
static css::Rule m_iconXRule;
|
||||||
|
static css::Rule m_iconYRule;
|
||||||
static css::Rule m_textAlignRule;
|
static css::Rule m_textAlignRule;
|
||||||
static css::Rule m_textColorRule;
|
static css::Rule m_textColorRule;
|
||||||
static css::Rule m_paddingLeftRule;
|
static css::Rule m_paddingLeftRule;
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define CLOSE_BUTTON_IN_EACH_TAB
|
|
||||||
|
|
||||||
#include "app/modules/gfx.h"
|
#include "app/modules/gfx.h"
|
||||||
#include "app/modules/gui.h"
|
#include "app/modules/gui.h"
|
||||||
#include "app/ui/skin/skin_theme.h"
|
#include "app/ui/skin/skin_theme.h"
|
||||||
@ -45,26 +43,6 @@ static WidgetType tabs_type()
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Tabs::ScrollButton : public Button
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ScrollButton(int direction, Tabs* tabs)
|
|
||||||
: Button("")
|
|
||||||
, m_direction(direction)
|
|
||||||
, m_tabs(tabs) {
|
|
||||||
}
|
|
||||||
|
|
||||||
int getDirection() const { return m_direction; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool onProcessMessage(Message* msg) override;
|
|
||||||
void onDisable() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_direction;
|
|
||||||
Tabs* m_tabs;
|
|
||||||
};
|
|
||||||
|
|
||||||
Tabs::Tabs(TabsDelegate* delegate)
|
Tabs::Tabs(TabsDelegate* delegate)
|
||||||
: Widget(tabs_type())
|
: Widget(tabs_type())
|
||||||
, m_delegate(delegate)
|
, m_delegate(delegate)
|
||||||
@ -73,32 +51,12 @@ Tabs::Tabs(TabsDelegate* delegate)
|
|||||||
setDoubleBuffered(true);
|
setDoubleBuffered(true);
|
||||||
|
|
||||||
m_hot = NULL;
|
m_hot = NULL;
|
||||||
|
m_hotCloseButton = false;
|
||||||
m_selected = NULL;
|
m_selected = NULL;
|
||||||
m_scrollX = 0;
|
m_scrollX = 0;
|
||||||
m_ani = ANI_NONE;
|
m_ani = ANI_NONE;
|
||||||
m_removedTab = NULL;
|
m_removedTab = NULL;
|
||||||
|
|
||||||
m_button_left = new ScrollButton(-1, this);
|
|
||||||
m_button_right = new ScrollButton(+1, this);
|
|
||||||
|
|
||||||
setup_mini_look(m_button_left);
|
|
||||||
setup_mini_look(m_button_right);
|
|
||||||
setup_bevels(m_button_left, 2, 0, 2, 0);
|
|
||||||
setup_bevels(m_button_right, 0, 2, 0, 2);
|
|
||||||
|
|
||||||
m_button_left->setFocusStop(false);
|
|
||||||
m_button_right->setFocusStop(false);
|
|
||||||
|
|
||||||
set_gfxicon_to_button(m_button_left,
|
|
||||||
PART_COMBOBOX_ARROW_LEFT,
|
|
||||||
PART_COMBOBOX_ARROW_LEFT_SELECTED,
|
|
||||||
PART_COMBOBOX_ARROW_LEFT_DISABLED, JI_CENTER | JI_MIDDLE);
|
|
||||||
|
|
||||||
set_gfxicon_to_button(m_button_right,
|
|
||||||
PART_COMBOBOX_ARROW_RIGHT,
|
|
||||||
PART_COMBOBOX_ARROW_RIGHT_SELECTED,
|
|
||||||
PART_COMBOBOX_ARROW_RIGHT_DISABLED, JI_CENTER | JI_MIDDLE);
|
|
||||||
|
|
||||||
initTheme();
|
initTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,15 +74,12 @@ Tabs::~Tabs()
|
|||||||
for (Tab* tab : m_list)
|
for (Tab* tab : m_list)
|
||||||
delete tab;
|
delete tab;
|
||||||
m_list.clear();
|
m_list.clear();
|
||||||
|
|
||||||
delete m_button_left; // widget
|
|
||||||
delete m_button_right; // widget
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tabs::addTab(TabView* tabView)
|
void Tabs::addTab(TabView* tabView)
|
||||||
{
|
{
|
||||||
Tab* tab = new Tab(tabView);
|
Tab* tab = new Tab(tabView);
|
||||||
calcTabWidth(tab);
|
tab->text = tab->view->getTabText();
|
||||||
|
|
||||||
m_list.push_back(tab);
|
m_list.push_back(tab);
|
||||||
|
|
||||||
@ -156,7 +111,6 @@ void Tabs::removeTab(TabView* tabView)
|
|||||||
|
|
||||||
it = m_list.erase(it);
|
it = m_list.erase(it);
|
||||||
|
|
||||||
// Width of the removed tab
|
|
||||||
if (m_removedTab) {
|
if (m_removedTab) {
|
||||||
delete m_removedTab;
|
delete m_removedTab;
|
||||||
m_removedTab = NULL;
|
m_removedTab = NULL;
|
||||||
@ -177,10 +131,8 @@ void Tabs::removeTab(TabView* tabView)
|
|||||||
|
|
||||||
void Tabs::updateTabsText()
|
void Tabs::updateTabsText()
|
||||||
{
|
{
|
||||||
for (Tab* tab : m_list) {
|
for (Tab* tab : m_list)
|
||||||
// Change text of the tab
|
tab->text = tab->view->getTabText();
|
||||||
calcTabWidth(tab);
|
|
||||||
}
|
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +210,6 @@ bool Tabs::onProcessMessage(Message* msg)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case kMouseDownMessage:
|
case kMouseDownMessage:
|
||||||
case kMouseUpMessage:
|
|
||||||
if (m_hot != NULL) {
|
if (m_hot != NULL) {
|
||||||
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
||||||
|
|
||||||
@ -267,13 +218,41 @@ bool Tabs::onProcessMessage(Message* msg)
|
|||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_hotCloseButton) {
|
||||||
|
if (!m_clickedCloseButton) {
|
||||||
|
m_clickedCloseButton = true;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Left button is processed in mouse down message, right
|
// Left button is processed in mouse down message, right
|
||||||
// button is processed in mouse up.
|
// button is processed in mouse up.
|
||||||
if (m_selected && m_delegate &&
|
if (m_selected && m_delegate &&
|
||||||
((mouseMsg->left() && msg->type() == kMouseDownMessage) ||
|
!m_clickedCloseButton &&
|
||||||
(!mouseMsg->left() && msg->type() == kMouseUpMessage))) {
|
mouseMsg->left()) {
|
||||||
m_delegate->clickTab(this, m_selected->view, mouseMsg->buttons());
|
m_delegate->clickTab(this, m_selected->view, mouseMsg->buttons());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
captureMouse();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case kMouseUpMessage:
|
||||||
|
if (hasCapture()) {
|
||||||
|
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
||||||
|
|
||||||
|
if (m_delegate && m_selected && m_selected == m_hot) {
|
||||||
|
if (m_hotCloseButton && m_clickedCloseButton) {
|
||||||
|
m_clickedCloseButton = false;
|
||||||
|
invalidate();
|
||||||
|
|
||||||
|
m_delegate->clickClose(this, m_selected->view);
|
||||||
|
}
|
||||||
|
else if (!mouseMsg->left()) {
|
||||||
|
m_delegate->clickTab(this, m_selected->view, mouseMsg->buttons());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
releaseMouse();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -303,12 +282,6 @@ bool Tabs::onProcessMessage(Message* msg)
|
|||||||
case ANI_NONE:
|
case ANI_NONE:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
case ANI_SCROLL: {
|
|
||||||
ScrollButton* button = dynamic_cast<ScrollButton*>(getManager()->getCapture());
|
|
||||||
if (button != NULL)
|
|
||||||
setScrollX(m_scrollX + button->getDirection()*8*static_cast<TimerMessage*>(msg)->count());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ANI_SMOOTH_SCROLL: {
|
case ANI_SMOOTH_SCROLL: {
|
||||||
if (m_ani_t == ANI_SMOOTH_SCROLL_TICKS) {
|
if (m_ani_t == ANI_SMOOTH_SCROLL_TICKS) {
|
||||||
stopAni();
|
stopAni();
|
||||||
@ -366,8 +339,9 @@ void Tabs::onPaint(PaintEvent& ev)
|
|||||||
box.x = box.x2();
|
box.x = box.x2();
|
||||||
|
|
||||||
// For each tab...
|
// For each tab...
|
||||||
|
int tabWidth = calcTabWidth();
|
||||||
for (Tab* tab : m_list) {
|
for (Tab* tab : m_list) {
|
||||||
box.w = tab->width;
|
box.w = tabWidth;
|
||||||
|
|
||||||
int x_delta = 0;
|
int x_delta = 0;
|
||||||
int y_delta = 0;
|
int y_delta = 0;
|
||||||
@ -377,19 +351,19 @@ void Tabs::onPaint(PaintEvent& ev)
|
|||||||
y_delta = box.h * (ANI_ADDING_TAB_TICKS - m_ani_t) / ANI_ADDING_TAB_TICKS;
|
y_delta = box.h * (ANI_ADDING_TAB_TICKS - m_ani_t) / ANI_ADDING_TAB_TICKS;
|
||||||
}
|
}
|
||||||
else if (m_ani == ANI_REMOVING_TAB && m_nextTabOfTheRemovedOne == tab) {
|
else if (m_ani == ANI_REMOVING_TAB && m_nextTabOfTheRemovedOne == tab) {
|
||||||
x_delta += m_removedTab->width
|
x_delta += tabWidth
|
||||||
- int(double(m_removedTab->width)*(1.0-std::exp(-10.0 * m_ani_t / (double)ANI_REMOVING_TAB_TICKS)));
|
- int(double(tabWidth)*(1.0-std::exp(-10.0 * m_ani_t / (double)ANI_REMOVING_TAB_TICKS)));
|
||||||
x_delta = MID(0, x_delta, m_removedTab->width);
|
x_delta = MID(0, x_delta, tabWidth);
|
||||||
|
|
||||||
// Draw deleted tab
|
// Draw deleted tab
|
||||||
if (m_removedTab) {
|
if (m_removedTab) {
|
||||||
gfx::Rect box2(box.x, box.y, x_delta, box.h);
|
gfx::Rect box2(box.x, box.y, x_delta, box.h);
|
||||||
drawTab(g, box2, m_removedTab, 0, false);
|
drawTab(g, box2, m_removedTab, 0, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
box.x += x_delta;
|
box.x += x_delta;
|
||||||
drawTab(g, box, tab, y_delta, (tab == m_selected));
|
drawTab(g, box, tab, y_delta, (tab == m_hot), (tab == m_selected));
|
||||||
|
|
||||||
box.x = box.x2();
|
box.x = box.x2();
|
||||||
}
|
}
|
||||||
@ -397,12 +371,12 @@ void Tabs::onPaint(PaintEvent& ev)
|
|||||||
if (m_ani == ANI_REMOVING_TAB && m_nextTabOfTheRemovedOne == NULL) {
|
if (m_ani == ANI_REMOVING_TAB && m_nextTabOfTheRemovedOne == NULL) {
|
||||||
// Draw deleted tab
|
// Draw deleted tab
|
||||||
if (m_removedTab) {
|
if (m_removedTab) {
|
||||||
int x_delta = m_removedTab->width
|
int x_delta = tabWidth
|
||||||
- int(double(m_removedTab->width)*(1.0-std::exp(-10.0 * m_ani_t / (double)ANI_REMOVING_TAB_TICKS)));
|
- int(double(tabWidth)*(1.0-std::exp(-10.0 * m_ani_t / (double)ANI_REMOVING_TAB_TICKS)));
|
||||||
x_delta = MID(0, x_delta, m_removedTab->width);
|
x_delta = MID(0, x_delta, tabWidth);
|
||||||
|
|
||||||
gfx::Rect box2(box.x, box.y, x_delta, box.h);
|
gfx::Rect box2(box.x, box.y, x_delta, box.h);
|
||||||
drawTab(g, box2, m_removedTab, 0, false);
|
drawTab(g, box2, m_removedTab, 0, false, false);
|
||||||
|
|
||||||
box.x += x_delta;
|
box.x += x_delta;
|
||||||
box.w = 0;
|
box.w = 0;
|
||||||
@ -437,22 +411,6 @@ void Tabs::onPreferredSize(PreferredSizeEvent& ev)
|
|||||||
ev.setPreferredSize(reqsize);
|
ev.setPreferredSize(reqsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tabs::onInitTheme(InitThemeEvent& ev)
|
|
||||||
{
|
|
||||||
Widget::onInitTheme(ev);
|
|
||||||
|
|
||||||
SkinTheme* theme = static_cast<SkinTheme*>(ev.getTheme());
|
|
||||||
|
|
||||||
m_button_left->setBgColor(theme->colors.tabActiveFace());
|
|
||||||
m_button_right->setBgColor(theme->colors.tabActiveFace());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Tabs::onSetText()
|
|
||||||
{
|
|
||||||
for (Tab* tab : m_list)
|
|
||||||
calcTabWidth(tab);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Tabs::selectTabInternal(Tab* tab)
|
void Tabs::selectTabInternal(Tab* tab)
|
||||||
{
|
{
|
||||||
m_selected = tab;
|
m_selected = tab;
|
||||||
@ -460,15 +418,30 @@ void Tabs::selectTabInternal(Tab* tab)
|
|||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tabs::drawTab(Graphics* g, const gfx::Rect& box, Tab* tab, int y_delta, bool selected)
|
void Tabs::drawTab(Graphics* g, const gfx::Rect& _box, Tab* tab, int y_delta,
|
||||||
|
bool hover, bool selected)
|
||||||
{
|
{
|
||||||
|
gfx::Rect box = _box;
|
||||||
|
|
||||||
// Is the tab outside the bounds of the widget?
|
// Is the tab outside the bounds of the widget?
|
||||||
if (box.x >= getBounds().x2() || box.x2() <= getBounds().x)
|
if (box.x >= getBounds().x2() || box.x2() <= getBounds().x)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (box.w < ui::guiscale()*8)
|
||||||
|
box.w = ui::guiscale()*8;
|
||||||
|
|
||||||
SkinTheme* theme = static_cast<SkinTheme*>(this->getTheme());
|
SkinTheme* theme = static_cast<SkinTheme*>(this->getTheme());
|
||||||
gfx::Color text_color;
|
gfx::Color text_color;
|
||||||
gfx::Color face_color;
|
gfx::Color face_color;
|
||||||
|
int clipTextRightSide;
|
||||||
|
|
||||||
|
gfx::Rect closeBox = getTabCloseButtonBounds(box);
|
||||||
|
if (closeBox.isEmpty())
|
||||||
|
clipTextRightSide = 4*ui::guiscale();
|
||||||
|
else {
|
||||||
|
closeBox.y += y_delta;
|
||||||
|
clipTextRightSide = closeBox.w;
|
||||||
|
}
|
||||||
|
|
||||||
// Selected
|
// Selected
|
||||||
if (selected) {
|
if (selected) {
|
||||||
@ -483,8 +456,14 @@ void Tabs::drawTab(Graphics* g, const gfx::Rect& box, Tab* tab, int y_delta, boo
|
|||||||
|
|
||||||
skin::Style::State state;
|
skin::Style::State state;
|
||||||
if (selected) state += skin::Style::active();
|
if (selected) state += skin::Style::active();
|
||||||
|
if (hover) state += skin::Style::hover();
|
||||||
|
|
||||||
if (box.w > 2) {
|
theme->styles.tab()->paint(g,
|
||||||
|
gfx::Rect(box.x, box.y+y_delta, box.w, box.h),
|
||||||
|
nullptr, state);
|
||||||
|
|
||||||
|
if (box.w > 8*ui::guiscale()) {
|
||||||
|
IntersectClip clip(g, gfx::Rect(box.x, box.y+y_delta, box.w-clipTextRightSide, box.h));
|
||||||
theme->styles.tab()->paint(g,
|
theme->styles.tab()->paint(g,
|
||||||
gfx::Rect(box.x, box.y+y_delta, box.w, box.h),
|
gfx::Rect(box.x, box.y+y_delta, box.w, box.h),
|
||||||
tab->text.c_str(), state);
|
tab->text.c_str(), state);
|
||||||
@ -494,12 +473,28 @@ void Tabs::drawTab(Graphics* g, const gfx::Rect& box, Tab* tab, int y_delta, boo
|
|||||||
gfx::Rect(box.x, box.y2(), box.w, getBounds().y2()-box.y2()),
|
gfx::Rect(box.x, box.y2(), box.w, getBounds().y2()-box.y2()),
|
||||||
nullptr, state);
|
nullptr, state);
|
||||||
|
|
||||||
#ifdef CLOSE_BUTTON_IN_EACH_TAB
|
// Close button
|
||||||
she::Surface* close_icon = theme->get_part(PART_WINDOW_CLOSE_BUTTON_NORMAL);
|
if (!closeBox.isEmpty()) {
|
||||||
g->drawRgbaSurface(close_icon,
|
skin::Style* style = theme->styles.tabCloseIcon();
|
||||||
box.x2() - 4*guiscale() - close_icon->width(),
|
if (m_delegate &&
|
||||||
box.y + box.h/2 - close_icon->height()/2+1 * guiscale());
|
m_delegate->isModified(this, tab->view) &&
|
||||||
#endif
|
(!hover || !m_hotCloseButton)) {
|
||||||
|
style = theme->styles.tabModifiedIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
state = skin::Style::State();
|
||||||
|
if (hover && m_hotCloseButton) {
|
||||||
|
state += skin::Style::hover();
|
||||||
|
if (selected)
|
||||||
|
state += skin::Style::active();
|
||||||
|
if (m_clickedCloseButton)
|
||||||
|
state += skin::Style::clicked();
|
||||||
|
}
|
||||||
|
else if (selected)
|
||||||
|
state += skin::Style::active();
|
||||||
|
|
||||||
|
style->paint(g, closeBox, nullptr, state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Tabs::TabsListIterator Tabs::getTabIteratorByView(TabView* tabView)
|
Tabs::TabsListIterator Tabs::getTabIteratorByView(TabView* tabView)
|
||||||
@ -527,10 +522,11 @@ int Tabs::getMaxScrollX()
|
|||||||
{
|
{
|
||||||
TabsListIterator it, end = m_list.end();
|
TabsListIterator it, end = m_list.end();
|
||||||
int x = 0;
|
int x = 0;
|
||||||
|
int tabWidth = calcTabWidth();
|
||||||
|
|
||||||
for (it = m_list.begin(); it != end; ++it) {
|
for (it = m_list.begin(); it != end; ++it) {
|
||||||
Tab* tab = *it;
|
Tab* tab = *it;
|
||||||
x += tab->width;
|
x += tabWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
x -= getBounds().w;
|
x -= getBounds().w;
|
||||||
@ -545,19 +541,20 @@ void Tabs::makeTabVisible(Tab* make_visible_this_tab)
|
|||||||
{
|
{
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int extra_x = getMaxScrollX() > 0 ? ARROW_W*2: 0;
|
int extra_x = getMaxScrollX() > 0 ? ARROW_W*2: 0;
|
||||||
|
int tabWidth = calcTabWidth();
|
||||||
|
|
||||||
for (Tab* tab : m_list) {
|
for (Tab* tab : m_list) {
|
||||||
if (tab == make_visible_this_tab) {
|
if (tab == make_visible_this_tab) {
|
||||||
if (x - m_scrollX < 0) {
|
if (x - m_scrollX < 0) {
|
||||||
setScrollX(x);
|
setScrollX(x);
|
||||||
}
|
}
|
||||||
else if (x + tab->width - m_scrollX > getBounds().w - extra_x) {
|
else if (x + tabWidth - m_scrollX > getBounds().w - extra_x) {
|
||||||
setScrollX(x + tab->width - getBounds().w + extra_x);
|
setScrollX(x + tabWidth - getBounds().w + extra_x);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
x += tab->width;
|
x += tabWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,56 +568,35 @@ void Tabs::setScrollX(int scroll_x)
|
|||||||
calculateHot();
|
calculateHot();
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need scroll buttons?
|
|
||||||
if (max_x > 0) {
|
|
||||||
// Add childs
|
|
||||||
if (!HAS_ARROWS(this)) {
|
|
||||||
addChild(m_button_left);
|
|
||||||
addChild(m_button_right);
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* disable/enable buttons */
|
|
||||||
m_button_left->setEnabled(m_scrollX > 0);
|
|
||||||
m_button_right->setEnabled(m_scrollX < max_x);
|
|
||||||
|
|
||||||
// Setup the position of each button
|
|
||||||
gfx::Rect rect = getBounds();
|
|
||||||
gfx::Rect box(rect.x2()-ARROW_W*2, rect.y, ARROW_W, rect.h-2);
|
|
||||||
m_button_left->setBounds(box);
|
|
||||||
|
|
||||||
box.x += ARROW_W;
|
|
||||||
m_button_right->setBounds(box);
|
|
||||||
}
|
|
||||||
// Remove buttons
|
|
||||||
else if (HAS_ARROWS(this)) {
|
|
||||||
removeChild(m_button_left);
|
|
||||||
removeChild(m_button_right);
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tabs::calculateHot()
|
void Tabs::calculateHot()
|
||||||
{
|
{
|
||||||
|
SkinTheme* theme = static_cast<SkinTheme*>(this->getTheme());
|
||||||
gfx::Rect rect = getBounds();
|
gfx::Rect rect = getBounds();
|
||||||
gfx::Rect box(rect.x-m_scrollX, rect.y, 0, rect.h-1);
|
gfx::Rect box(rect.x-m_scrollX, rect.y, 0, rect.h-1);
|
||||||
Tab *hot = NULL;
|
gfx::Point mousePos = ui::get_mouse_position();
|
||||||
|
Tab* hot = NULL;
|
||||||
|
bool hotCloseButton = false;
|
||||||
|
int tabWidth = calcTabWidth();
|
||||||
|
|
||||||
// For each tab
|
// For each tab
|
||||||
for (Tab* tab : m_list) {
|
for (Tab* tab : m_list) {
|
||||||
box.w = tab->width;
|
box.w = tabWidth;
|
||||||
|
|
||||||
if (box.contains(ui::get_mouse_position())) {
|
if (box.contains(mousePos)) {
|
||||||
hot = tab;
|
hot = tab;
|
||||||
|
hotCloseButton = getTabCloseButtonBounds(box).contains(mousePos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
box.x += box.w;
|
box.x += box.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_hot != hot) {
|
if (m_hot != hot ||
|
||||||
|
m_hotCloseButton != hotCloseButton) {
|
||||||
m_hot = hot;
|
m_hot = hot;
|
||||||
|
m_hotCloseButton = hotCloseButton;
|
||||||
|
|
||||||
if (m_delegate)
|
if (m_delegate)
|
||||||
m_delegate->mouseOverTab(this, m_hot ? m_hot->view: NULL);
|
m_delegate->mouseOverTab(this, m_hot ? m_hot->view: NULL);
|
||||||
@ -629,29 +605,29 @@ void Tabs::calculateHot()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tabs::calcTabWidth(Tab* tab)
|
int Tabs::calcTabWidth()
|
||||||
{
|
{
|
||||||
// Cache current tab text
|
SkinTheme* theme = static_cast<SkinTheme*>(this->getTheme());
|
||||||
tab->text = tab->view->getTabText();
|
int tabWidth = theme->dimensions.tabsWidth();
|
||||||
|
|
||||||
int border = 4*guiscale();
|
if (tabWidth * m_list.size() > (size_t)getBounds().w) {
|
||||||
#ifdef CLOSE_BUTTON_IN_EACH_TAB
|
tabWidth = getBounds().w / m_list.size();
|
||||||
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
|
tabWidth = MAX(2*ui::guiscale(), tabWidth);
|
||||||
int close_icon_w = theme->get_part(PART_WINDOW_CLOSE_BUTTON_NORMAL)->width();
|
}
|
||||||
tab->width = (border + getFont()->textLength(tab->text.c_str()) + border + close_icon_w + border);
|
|
||||||
#else
|
return tabWidth;
|
||||||
tab->width = (border + getFont()->textLength(tab->text.c_str()) + border);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tabs::startScrolling()
|
gfx::Rect Tabs::getTabCloseButtonBounds(const gfx::Rect& box)
|
||||||
{
|
{
|
||||||
startAni(ANI_SCROLL);
|
SkinTheme* theme = static_cast<SkinTheme*>(this->getTheme());
|
||||||
}
|
int iconW = theme->dimensions.tabsCloseIconWidth();
|
||||||
|
int iconH = theme->dimensions.tabsCloseIconHeight();
|
||||||
|
|
||||||
void Tabs::stopScrolling()
|
if (box.w-iconW > 4*ui::guiscale())
|
||||||
{
|
return gfx::Rect(box.x2()-iconW, box.y+box.h/2-iconH/2, iconW, iconH);
|
||||||
stopAni();
|
else
|
||||||
|
return gfx::Rect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tabs::startAni(Ani ani)
|
void Tabs::startAni(Ani ani)
|
||||||
@ -671,38 +647,4 @@ void Tabs::stopAni()
|
|||||||
m_timer.stop();
|
m_timer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tabs::ScrollButton::onProcessMessage(Message* msg)
|
|
||||||
{
|
|
||||||
switch (msg->type()) {
|
|
||||||
|
|
||||||
case kMouseDownMessage:
|
|
||||||
captureMouse();
|
|
||||||
m_tabs->startScrolling();
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case kMouseUpMessage:
|
|
||||||
if (hasCapture())
|
|
||||||
releaseMouse();
|
|
||||||
|
|
||||||
m_tabs->stopScrolling();
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return Button::onProcessMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Tabs::ScrollButton::onDisable()
|
|
||||||
{
|
|
||||||
Button::onDisable();
|
|
||||||
|
|
||||||
if (hasCapture())
|
|
||||||
releaseMouse();
|
|
||||||
|
|
||||||
if (isSelected()) {
|
|
||||||
m_tabs->stopScrolling();
|
|
||||||
setSelected(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -40,9 +40,14 @@ namespace app {
|
|||||||
// Called when the user presses a mouse button over a tab.
|
// Called when the user presses a mouse button over a tab.
|
||||||
virtual void clickTab(Tabs* tabs, TabView* tabView, ui::MouseButtons buttons) = 0;
|
virtual void clickTab(Tabs* tabs, TabView* tabView, ui::MouseButtons buttons) = 0;
|
||||||
|
|
||||||
|
// When the tab close button is pressed.
|
||||||
|
virtual void clickClose(Tabs* tabs, TabView* tabView) = 0;
|
||||||
|
|
||||||
// Called when the mouse is over a tab (the data can be null if the
|
// Called when the mouse is over a tab (the data can be null if the
|
||||||
// mouse just leave all tabs)
|
// mouse just leave all tabs)
|
||||||
virtual void mouseOverTab(Tabs* tabs, TabView* tabView) = 0;
|
virtual void mouseOverTab(Tabs* tabs, TabView* tabView) = 0;
|
||||||
|
|
||||||
|
virtual bool isModified(Tabs* tabs, TabView* tabView) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Tabs control. Used to show opened documents.
|
// Tabs control. Used to show opened documents.
|
||||||
@ -50,9 +55,8 @@ namespace app {
|
|||||||
struct Tab {
|
struct Tab {
|
||||||
TabView* view;
|
TabView* view;
|
||||||
std::string text;
|
std::string text;
|
||||||
int width;
|
|
||||||
|
|
||||||
Tab(TabView* view) : view(view), width(0) {
|
Tab(TabView* view) : view(view) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -62,7 +66,6 @@ namespace app {
|
|||||||
enum Ani { ANI_NONE,
|
enum Ani { ANI_NONE,
|
||||||
ANI_ADDING_TAB,
|
ANI_ADDING_TAB,
|
||||||
ANI_REMOVING_TAB,
|
ANI_REMOVING_TAB,
|
||||||
ANI_SCROLL,
|
|
||||||
ANI_SMOOTH_SCROLL };
|
ANI_SMOOTH_SCROLL };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -78,33 +81,31 @@ namespace app {
|
|||||||
void selectPreviousTab();
|
void selectPreviousTab();
|
||||||
TabView* getSelectedTab();
|
TabView* getSelectedTab();
|
||||||
|
|
||||||
void startScrolling();
|
|
||||||
void stopScrolling();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool onProcessMessage(ui::Message* msg) override;
|
bool onProcessMessage(ui::Message* msg) override;
|
||||||
void onPaint(ui::PaintEvent& ev) override;
|
void onPaint(ui::PaintEvent& ev) override;
|
||||||
void onResize(ui::ResizeEvent& ev) override;
|
void onResize(ui::ResizeEvent& ev) override;
|
||||||
void onPreferredSize(ui::PreferredSizeEvent& ev) override;
|
void onPreferredSize(ui::PreferredSizeEvent& ev) override;
|
||||||
void onInitTheme(ui::InitThemeEvent& ev) override;
|
|
||||||
void onSetText() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startAni(Ani ani);
|
void startAni(Ani ani);
|
||||||
void stopAni();
|
void stopAni();
|
||||||
|
|
||||||
void selectTabInternal(Tab* tab);
|
void selectTabInternal(Tab* tab);
|
||||||
void drawTab(ui::Graphics* g, const gfx::Rect& box, Tab* tab, int y_delta, bool selected);
|
void drawTab(ui::Graphics* g, const gfx::Rect& box, Tab* tab, int y_delta, bool hover, bool selected);
|
||||||
TabsListIterator getTabIteratorByView(TabView* tabView);
|
TabsListIterator getTabIteratorByView(TabView* tabView);
|
||||||
Tab* getTabByView(TabView* tabView);
|
Tab* getTabByView(TabView* tabView);
|
||||||
int getMaxScrollX();
|
int getMaxScrollX();
|
||||||
void makeTabVisible(Tab* tab);
|
void makeTabVisible(Tab* tab);
|
||||||
void setScrollX(int scroll_x);
|
void setScrollX(int scroll_x);
|
||||||
void calculateHot();
|
void calculateHot();
|
||||||
void calcTabWidth(Tab* tab);
|
int calcTabWidth();
|
||||||
|
gfx::Rect getTabCloseButtonBounds(const gfx::Rect& box);
|
||||||
|
|
||||||
TabsList m_list;
|
TabsList m_list;
|
||||||
Tab* m_hot;
|
Tab* m_hot;
|
||||||
|
bool m_hotCloseButton;
|
||||||
|
bool m_clickedCloseButton;
|
||||||
Tab* m_selected;
|
Tab* m_selected;
|
||||||
int m_scrollX;
|
int m_scrollX;
|
||||||
|
|
||||||
@ -119,11 +120,6 @@ namespace app {
|
|||||||
int m_ani_t; // Number of ticks from the beginning of the animation
|
int m_ani_t; // Number of ticks from the beginning of the animation
|
||||||
Tab* m_removedTab;
|
Tab* m_removedTab;
|
||||||
Tab* m_nextTabOfTheRemovedOne;
|
Tab* m_nextTabOfTheRemovedOne;
|
||||||
|
|
||||||
// Buttons to scroll tabs (useful when there are more tabs than visible area)
|
|
||||||
class ScrollButton;
|
|
||||||
ScrollButton* m_button_left;
|
|
||||||
ScrollButton* m_button_right;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
Loading…
x
Reference in New Issue
Block a user