[gnome-builder] style: land new styling for view stack header
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] style: land new styling for view stack header
- Date: Mon, 21 Dec 2015 08:03:18 +0000 (UTC)
commit 4808a100fc05ce4486d2b87fc73d81b1c2c6cb15
Author: Christian Hergert <chergert redhat com>
Date: Tue Dec 8 00:44:20 2015 -0800
style: land new styling for view stack header
data/theme/Adwaita-dark.css | 133 ++++++++++-
data/theme/Adwaita-shared.css | 74 +------
data/theme/Adwaita.css | 143 ++++++++++-
data/theme/shared.css | 8 +
data/ui/ide-editor-view.ui | 23 +--
data/ui/ide-layout-stack.ui | 303 ++++++++++++-----------
data/ui/ide-layout-tab-bar.ui | 72 ++++++
data/ui/ide-layout-tab.ui | 137 +++++++++++
libide/Makefile.am | 4 +
libide/editor/ide-editor-view-actions.c | 19 +--
libide/editor/ide-editor-view-private.h | 1 +
libide/ide-layout-grid.c | 2 +
libide/ide-layout-stack-actions.c | 10 +-
libide/ide-layout-stack-private.h | 16 +-
libide/ide-layout-stack.c | 287 +++-------------------
libide/ide-layout-tab-bar.c | 403 +++++++++++++++++++++++++++++++
libide/ide-layout-tab-bar.h | 36 +++
libide/ide-layout-tab.c | 243 +++++++++++++++++++
libide/ide-layout-tab.h | 35 +++
libide/resources/libide.gresource.xml | 2 +
20 files changed, 1420 insertions(+), 531 deletions(-)
---
diff --git a/data/theme/Adwaita-dark.css b/data/theme/Adwaita-dark.css
index 2d13ecf..571840c 100644
--- a/data/theme/Adwaita-dark.css
+++ b/data/theme/Adwaita-dark.css
@@ -71,7 +71,7 @@ box.horizontal.search-bar:backdrop {
workbench > GtkOverlay > stack > box > stackswitcher.vertical:first-child {
- background: #313434;
+ background: #2e3436;
}
workbench > GtkOverlay > stack > box > stackswitcher.vertical:first-child button {
padding: 8px 10px 8px 10px;
@@ -86,6 +86,137 @@ workbench > GtkOverlay > stack > box > stackswitcher.vertical:first-child button
}
+
omnisearchrow {
color: #eeeeec;
}
+
+
+
+
+layouttabbar {
+ background-image: none;
+ background-color: #2e3436;
+ border-style: none;
+ border-radius: 0px;
+ border-bottom: 1px solid #1c1f1f;
+ color: #2e3436;
+ box-shadow: 0px 5px 5px -10px #101010 inset;
+}
+
+layouttabbar button {
+ background-image: none;
+ background-color: transparent;
+ color: #585858;
+ border-style: none;
+ border-radius: 0px;
+ box-shadow: none;
+ padding: 9px;
+}
+
+layouttabbar > box > button:hover {
+ color: #eeeeec;
+}
+
+layouttab {
+ background-image: none;
+ background-color: transparent;
+ border-style: none;
+ border-radius: 0 0 3px 3px;
+ border-bottom: 1px solid @borders;
+ color: #c8c8c8;
+}
+
+layoutstack.focused layouttab {
+ background-color: #343939;
+ border-bottom: 3px solid #215d9c;
+ border-left: 1px solid #282b2b;
+ border-right: 1px solid #282b2b;
+ box-shadow: 0px 5px 5px -10px #101010 inset;
+}
+
+layouttab button {
+ background-image: none;
+ background-color: transparent;
+ color: #6c6f6e;
+ border-style: none;
+ border-radius: 0px;
+ box-shadow: none;
+}
+
+layouttab label {
+ color: #eeeeec;
+ font-size: 0.9em;
+ text-shadow: 0 1px #101010;
+}
+
+layouttab label:hover {
+ color: black;
+}
+
+layouttab label:backdrop {
+ text-shadow: none;
+}
+
+layouttab separator {
+ color: transparent;
+}
+
+layoutstack.focused layouttab separator {
+ color: #484848;
+}
+
+layouttab:backdrop, layouttabbar:backdrop {
+ box-shadow: none;
+}
+
+layoutstack.empty layouttab,
+layoutstack.empty layouttab button,
+layoutstack.empty layouttab separator {
+ color: transparent;
+ background-color: transparent;
+}
+
+layoutstack layouttab button.close {
+ border-style: solid;
+ border-radius: 5px;
+ border-width: 1px;
+ border-color: transparent;
+ color: #acadae;
+ padding: 1px;
+ margin: 0px;
+}
+
+layoutstack layouttab button.close:hover {
+ border-color: #1c1f1f;
+ color: #eeeeec;
+}
+
+layoutstack layouttab button.close:active {
+ border-color: #1c1f1f;
+ color: #eeeeec;
+ background-image: linear-gradient(#2e3436, #2d3232);
+}
+
+.views-list row {
+ padding: 6px;
+}
+
+.views-list row button {
+ box-shadow: none;
+ padding: 0px;
+ border-style: none;
+ border-width: 0px;
+ background-image: none;
+ background-color: transparent;
+ color: #acadae;
+ opacity: 0.0;
+}
+
+.views-list row:selected button {
+ color: white;
+}
+
+.views-list row:hover button {
+ opacity: 1.0;
+}
diff --git a/data/theme/Adwaita-shared.css b/data/theme/Adwaita-shared.css
index baabbda..7696d36 100644
--- a/data/theme/Adwaita-shared.css
+++ b/data/theme/Adwaita-shared.css
@@ -9,78 +9,6 @@ GbEditorTweakWidget GtkScrolledWindow {
}
-/*
- * View stack styling.
- */
-layoutstack > box.vertical > box.header.notebook {
- background-color: shade (@theme_bg_color, 0.95);
- border-bottom: 1px solid @borders;
-}
-layoutstack.focused > box.vertical > box.header.notebook,
-layoutstack.backdrop.focused > box.vetical > box.header.notebook {
- background-color: shade (@theme_bg_color, 0.90);
-}
-layoutpane.focused > box.vertical > box.horizontal.notebook.header,
-layoutpane.focused > box.vertical > box.horizontal.notebook.header.backdrop {
- background-color: shade (@theme_bg_color, 0.90);
-}
-layoutstack > box.vertical > box.header.notebook.horizontal > GtkEventBox > box.horizontal > button,
-layoutstack > box.vertical > box.header.notebook.horizontal > GtkEventBox > box.horizontal > box > box >
button {
- background-image: none;
- border-bottom: 1px solid transparent;
- border-radius: 0px;
- border: 1px solid transparent;
- box-shadow: 0px 0px 0px;
- margin: 0px;
- opacity: 0.55;
- padding: 3px 8px 4px;
-}
-layoutstack > box.vertical > box.header.notebook.horizontal > GtkEventBox > box.horizontal > box.navigation
button {
- background-image: none;
- border-bottom: 1px solid transparent;
- border-radius: 0px;
- border: 1px solid transparent;
- box-shadow: 0px 0px 0px;
- margin: 0px;
- opacity: 0.55;
- padding: 6px 4px;
-}
-layoutpane > box.vertical > box.notebook.header > stackswitcher > button {
- background-image: none;
- border-bottom: 1px solid transparent;
- border-radius: 0px;
- border: 1px solid transparent;
- box-shadow: 0px 0px 0px;
- margin: 0px;
- opacity: 0.55;
- padding: 3px 0px 3px;
-}
-layoutpane > box.vertical > box.horizontal.notebook.header > stackswitcher button:checked,
-layoutstack > box.vertical > box.header.notebook.horizontal > GtkEventBox > box.horizontal > box > box >
button:checked,
-layoutstack > box.vertical > box.header.notebook.horizontal > GtkEventBox > box.horizontal > button:checked {
- box-shadow: 0px 2px 0px @theme_fg_color;
- color: @theme_fg_color;
-}
-layoutpane > box.vertical > box.notebook.header.horizontal > stackswitcher > button:hover,
-layoutstack > box.vertical > box.header.notebook.horizontal > GtkEventBox > box.horizontal > box.navigation
button:hover,
-layoutstack > box.vertical > box.header.notebook.horizontal > GtkEventBox > box.horizontal > button:hover,
-layoutstack > box.vertical > box.header.notebook.horizontal > GtkEventBox > box.horizontal > box > box >
button:hover {
- border: 1px solid transparent;
- box-shadow: 0px 2px 0px mix(@theme_fg_color, @theme_bg_color, 0.25);
-}
-layoutstack > box.vertical > box.header.notebook > GtkEventBox > box.horizontal > box.navigation > button {
- padding-left: 4px;
- padding-right: 4px;
-}
-layoutstack > box.vertical > box.header.notebook.horizontal > GtkEventBox > box.horizontal >
button.document-button {
- padding: 0px;
-}
-layoutstack > box.vertical > box.header.notebook.horizontal > GtkEventBox > box.horizontal >
button.document-button > box > GtkArrow {
- opacity: 0.35;
- padding-right: 0px;
- margin-right: 0px;
-}
-
/* FileChooserButton|Entry */
box.linked-on-right button {
@@ -93,6 +21,7 @@ box.linked-on-right button {
/*
* layout pane header styling.
*/
+/*
layoutpane box.header.notebook {
border-bottom: 1px solid @borders;
}
@@ -115,6 +44,7 @@ layoutpane stackswitcher button:checked {
layoutpane layoutstack box.header.notebook GtkSeparator.vertical {
opacity: 0.75;
}
+*/
/*
diff --git a/data/theme/Adwaita.css b/data/theme/Adwaita.css
index 2e2b086..c3cc66d 100644
--- a/data/theme/Adwaita.css
+++ b/data/theme/Adwaita.css
@@ -3,11 +3,11 @@
workbench treeview.view {
color: #555753;
- background-color: #eeeeec;
+ background-color: #f6f7f8;
}
workbench treeview.view:backdrop {
color: #888a85;
- background-color: #efefef;
+ background-color: #f6f7f8;
}
workbench treeview.view.cell:selected {
color: #fff;
@@ -44,17 +44,6 @@ treeview:backdrop.dim-label {
}
-GbAccelLabel .frame {
- background-color: #fefefe;
- border: 1px solid #cecece;
- border-radius: 5px;
- box-shadow: 0px 1px 0px #fff inset,
- 0px -2px 0px #dedede inset;
- color: #555753;
- padding: 3px 8px 3px 8px;
-}
-
-
box.horizontal.search-bar {
background: none;
background-color: #d6d6d6;
@@ -88,3 +77,131 @@ workbench > GtkOverlay > stack > box > stackswitcher.vertical:first-child button
omnisearchrow {
color: #2e3436;
}
+
+
+
+
+
+layouttabbar {
+ background-image: none;
+ background-color: #d6d6d6;
+ border-style: none;
+ border-radius: 0px;
+ border-bottom: 1px solid #919191;
+ color: #2e3436;
+ box-shadow: 0px 5px 5px -10px #2e3436 inset;
+}
+
+layouttabbar button {
+ background-image: none;
+ background-color: transparent;
+ color: #585858;
+ border-style: none;
+ border-radius: 0px;
+ box-shadow: none;
+ padding: 9px;
+}
+
+layouttab {
+ background-image: none;
+ background-color: transparent;
+ border-style: none;
+ border-radius: 0 0 3px 3px;
+ border-bottom: 1px solid @borders;
+ color: #c8c8c8;
+}
+
+layoutstack.focused layouttab {
+ background-color: #e1e1e1;
+ border-bottom: 3px solid #4a90d9;
+ border-left: 1px solid #c0c0c0;
+ border-right: 1px solid #c0c0c0;
+ box-shadow: 0px 5px 5px -10px #2e3436 inset;
+}
+
+layouttab button {
+ background-image: none;
+ background-color: transparent;
+ color: #919191;
+ border-style: none;
+ border-radius: 0px;
+ box-shadow: none;
+}
+
+layouttab label {
+ color: #2e3436;
+ font-size: 0.9em;
+ text-shadow: 0 1px white;
+}
+
+layouttab label:hover {
+ color: black;
+}
+
+layouttab label:backdrop {
+ text-shadow: none;
+}
+
+layouttab separator {
+ color: transparent;
+}
+
+layoutstack.focused layouttab separator {
+ color: #babdb6;
+}
+
+layouttab:backdrop, layouttabbar:backdrop {
+ box-shadow: none;
+}
+
+layoutstack.empty layouttab,
+layoutstack.empty layouttab button,
+layoutstack.empty layouttab separator {
+ color: transparent;
+ background-color: transparent;
+}
+
+layoutstack layouttab button.close {
+ border-style: solid;
+ border-radius: 5px;
+ border-width: 1px;
+ border-color: transparent;
+ color: #acadae;
+ padding: 1px;
+ margin: 0px;
+}
+
+layoutstack layouttab button.close:hover {
+ border-color: #a1a1a1;
+ color: #2e3436;
+}
+
+layoutstack layouttab button.close:active {
+ border-color: #a1a1a1;
+ background-image: linear-gradient(#d6d6d6, #e0e0e0);
+ color: #2e3436;
+ box-shadow: 0px 0px 2px #c8c8c8 inset;
+}
+
+.views-list row {
+ padding: 6px;
+}
+
+.views-list row button {
+ box-shadow: none;
+ padding: 0px;
+ border-style: none;
+ border-width: 0px;
+ background-image: none;
+ background-color: transparent;
+ color: #babdb6;
+ opacity: 0.0;
+}
+
+.views-list row:selected button {
+ color: white;
+}
+
+.views-list row:hover button {
+ opacity: 1.0;
+}
diff --git a/data/theme/shared.css b/data/theme/shared.css
index b278b50..794134c 100644
--- a/data/theme/shared.css
+++ b/data/theme/shared.css
@@ -164,3 +164,11 @@ progressbar.osd progress {
border-style: none;
border-radius: 0;
}
+
+
+layouttab box.navigation button:first-child {
+ padding-right: 6px;
+}
+layouttab box.navigation button:last-child {
+ padding-left: 6px;
+}
diff --git a/data/ui/ide-editor-view.ui b/data/ui/ide-editor-view.ui
index 2f02bb7..569700f 100644
--- a/data/ui/ide-editor-view.ui
+++ b/data/ui/ide-editor-view.ui
@@ -105,8 +105,8 @@
<object class="GtkSeparator">
<property name="margin-start">3</property>
<property name="margin-end">3</property>
- <property name="margin-top">4</property>
- <property name="margin-bottom">4</property>
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
<property name="orientation">vertical</property>
<property name="visible">true</property>
</object>
@@ -116,11 +116,6 @@
<property name="popover">goto_line_popover</property>
<property name="focus-on-click">false</property>
<property name="visible">true</property>
- <style>
- <class name="dim-label"/>
- <class name="text-button"/>
- <class name="flat"/>
- </style>
<child>
<object class="GtkLabel" id="cursor_label">
<property name="label">1:1</property>
@@ -134,8 +129,8 @@
<object class="GtkSeparator">
<property name="margin-start">3</property>
<property name="margin-end">3</property>
- <property name="margin-top">4</property>
- <property name="margin-bottom">4</property>
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
<property name="orientation">vertical</property>
<property name="visible">true</property>
</object>
@@ -143,13 +138,8 @@
<child>
<object class="GtkMenuButton" id="tweak_button">
<property name="focus-on-click">false</property>
- <property name="popover">popover</property>
+ <property name="popover">tweak_popover</property>
<property name="visible">true</property>
- <style>
- <class name="dim-label"/>
- <class name="text-button"/>
- <class name="flat"/>
- </style>
</object>
</child>
</object>
@@ -157,7 +147,7 @@
</object>
</child>
</template>
- <object class="GtkPopover" id="popover">
+ <object class="GtkPopover" id="tweak_popover">
<child>
<object class="IdeEditorTweakWidget" id="tweak_widget">
<property name="border-width">12</property>
@@ -166,7 +156,6 @@
</child>
</object>
<object class="EggSimplePopover" id="goto_line_popover">
- <property name="visible">true</property>
<property name="title" translatable="yes">Go to Line</property>
<property name="button-text" translatable="yes">Go</property>
</object>
diff --git a/data/ui/ide-layout-stack.ui b/data/ui/ide-layout-stack.ui
index 2f51f5b..3d15f71 100644
--- a/data/ui/ide-layout-stack.ui
+++ b/data/ui/ide-layout-stack.ui
@@ -7,9 +7,15 @@
<property name="orientation">vertical</property>
<property name="visible">true</property>
<child>
+ <object class="IdeLayoutTabBar" id="tab_bar">
+ <property name="stack">stack</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
- <property name="visible">true</property>
+ <property name="visible">false</property>
<style>
<class name="notebook"/>
<class name="header"/>
@@ -24,200 +30,211 @@
<property name="orientation">horizontal</property>
<property name="hexpand">true</property>
<property name="visible">true</property>
- <property name="margin-bottom">3</property>
- <property name="margin-end">7</property>
- <property name="margin-start">6</property>
- <property name="margin-top">3</property>
<child>
- <object class="GtkMenuButton" id="views_button">
+ <object class="GtkBox">
+ <property name="hexpand">true</property>
<property name="visible">true</property>
- <property name="focus-on-click">false</property>
- <property name="popover">views_popover</property>
- <property name="sensitive">false</property>
<style>
- <class name="image-button"/>
- <class name="flat"/>
+ <class name="tab"/>
</style>
<child>
- <object class="GtkImage">
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
<property name="visible">true</property>
- <property name="icon-name">view-list-symbolic</property>
+ <style>
+ <class name="navigation"/>
+ </style>
+ <child>
+ <object class="GtkButton" id="go_backward">
+ <property name="visible">true</property>
+ <property name="action-name">view-stack.go-backward</property>
+ <property name="focus-on-click">false</property>
+ <style>
+ <class name="flat"/>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-previous-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="go_forward">
+ <property name="visible">true</property>
+ <property name="action-name">view-stack.go-forward</property>
+ <property name="focus-on-click">false</property>
+ <style>
+ <class name="flat"/>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
</object>
</child>
- </object>
- <packing>
- <property name="pack-type">start</property>
- </packing>
- </child>
- <child>
- <object class="GtkSeparator">
- <property name="margin-start">3</property>
- <property name="margin-end">3</property>
- <property name="margin-top">4</property>
- <property name="margin-bottom">4</property>
- <property name="orientation">vertical</property>
- <property name="visible">true</property>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="orientation">horizontal</property>
- <property name="visible">true</property>
- <style>
- <class name="navigation"/>
- </style>
<child>
- <object class="GtkButton" id="go_backward">
+ <object class="GtkSeparator">
+ <property name="margin-start">3</property>
+ <property name="margin-end">3</property>
+ <property name="margin-top">4</property>
+ <property name="margin-bottom">4</property>
+ <property name="orientation">vertical</property>
<property name="visible">true</property>
- <property name="action-name">view-stack.go-backward</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="document_button">
<property name="focus-on-click">false</property>
+ <property name="hexpand">false</property>
+ <property name="popover">popover</property>
+ <!-- Sensitive is not being respected,
+ likely due to popover being set. -->
+ <property name="sensitive">false</property>
+ <property name="visible">true</property>
<style>
<class name="flat"/>
- <class name="image-button"/>
+ <class name="text-button"/>
+ <class name="document-button"/>
</style>
<child>
- <object class="GtkImage">
- <property name="icon-name">go-previous-symbolic</property>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
<property name="visible">true</property>
+ <child>
+ <object class="GtkLabel" id="title_label">
+ <property name="hexpand">false</property>
+ <property name="visible">true</property>
+ <property name="ellipsize">start</property>
+ <property name="valign">baseline</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="modified_label">
+ <property name="halign">fill</property>
+ <property name="hexpand">true</property>
+ <property name="xalign">1.0</property>
+ <property name="label">•</property>
+ <property name="valign">baseline</property>
+ <property name="visible">false</property>
+ </object>
+ <packing>
+ <property name="pack-type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkArrow">
+ <property name="arrow-type">down</property>
+ <property name="margin-top">2</property>
+ <property name="valign">baseline</property>
+ <property name="visible">true</property>
+ </object>
+ <packing>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
</object>
</child>
</object>
+ <packing>
+ <property name="padding">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="controls">
+ <property name="visible">true</property>
+ </object>
+ <packing>
+ <property name="pack-type">end</property>
+ <property name="position">6</property>
+ </packing>
</child>
<child>
- <object class="GtkButton" id="go_forward">
+ <object class="GtkSeparator">
+ <property name="margin-start">3</property>
+ <property name="margin-end">3</property>
+ <property name="margin-top">4</property>
+ <property name="margin-bottom">4</property>
+ <property name="orientation">vertical</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="close_button">
+ <property name="action-name">view-stack.close</property>
<property name="visible">true</property>
- <property name="action-name">view-stack.go-forward</property>
<property name="focus-on-click">false</property>
<style>
- <class name="flat"/>
<class name="image-button"/>
+ <class name="flat"/>
+ <class name="small-button"/>
</style>
<child>
<object class="GtkImage">
- <property name="icon-name">go-next-symbolic</property>
<property name="visible">true</property>
+ <property name="icon-name">window-close-symbolic</property>
</object>
</child>
</object>
+ <packing>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
</child>
</object>
</child>
<child>
- <object class="GtkSeparator">
- <property name="margin-start">3</property>
- <property name="margin-end">3</property>
- <property name="margin-top">4</property>
- <property name="margin-bottom">4</property>
- <property name="orientation">vertical</property>
- <property name="visible">true</property>
- </object>
- </child>
- <child>
- <object class="GtkMenuButton" id="document_button">
- <property name="focus-on-click">false</property>
- <property name="hexpand">false</property>
- <property name="popover">popover</property>
- <!-- Sensitive is not being respected,
- likely due to popover being set. -->
- <property name="sensitive">false</property>
+ <object class="GtkBox">
<property name="visible">true</property>
<style>
- <class name="flat"/>
- <class name="text-button"/>
- <class name="document-button"/>
+ <class name="tab-controls"/>
</style>
<child>
- <object class="GtkBox">
- <property name="spacing">6</property>
+ <object class="GtkMenuButton" id="views_button">
<property name="visible">true</property>
+ <property name="focus-on-click">false</property>
+ <property name="popover">views_popover</property>
+ <property name="sensitive">false</property>
<child>
- <object class="GtkLabel" id="title_label">
- <property name="hexpand">false</property>
- <property name="visible">true</property>
- <property name="ellipsize">start</property>
- <property name="valign">baseline</property>
- </object>
- </child>
- <child>
- <object class="GtkLabel" id="modified_label">
- <property name="halign">fill</property>
- <property name="hexpand">true</property>
- <property name="xalign">1.0</property>
- <property name="label">•</property>
- <property name="valign">baseline</property>
- <property name="visible">false</property>
- </object>
- <packing>
- <property name="pack-type">end</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkArrow">
- <property name="arrow-type">down</property>
- <property name="margin-top">2</property>
- <property name="valign">baseline</property>
+ <object class="GtkImage">
<property name="visible">true</property>
+ <property name="icon-name">view-more-symbolic</property>
</object>
- <packing>
- <property name="pack-type">end</property>
- <property name="position">0</property>
- </packing>
</child>
</object>
+ <packing>
+ <property name="pack-type">end</property>
+ <property name="position">1</property>
+ </packing>
</child>
- </object>
- <packing>
- <property name="padding">6</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="close_button">
- <property name="action-name">view-stack.close</property>
- <property name="visible">true</property>
- <property name="focus-on-click">false</property>
- <style>
- <class name="image-button"/>
- <class name="flat"/>
- <class name="small-button"/>
- </style>
<child>
- <object class="GtkImage">
+ <object class="GtkButton" id="add_document">
+ <property name="action-name">perspective.new-file</property>
<property name="visible">true</property>
- <property name="icon-name">window-close-symbolic</property>
+ <property name="focus-on-click">false</property>
+ <property name="sensitive">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">true</property>
+ <property name="icon-name">list-add-symbolic</property>
+ </object>
+ </child>
</object>
+ <packing>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
</child>
</object>
- <packing>
- <property name="pack-type">end</property>
- </packing>
- </child>
- <child>
- <object class="GtkSeparator">
- <property name="margin-start">3</property>
- <property name="margin-end">3</property>
- <property name="margin-top">4</property>
- <property name="margin-bottom">4</property>
- <property name="orientation">vertical</property>
- <property name="visible">true</property>
- </object>
- <packing>
- <!--
- this padding is to make things line up with header bar.
- unfortunately, this was annoying to get right with css.
- feel free to come fix it.
- -->
- <property name="padding">1</property>
- <property name="pack-type">end</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="controls">
- <property name="visible">true</property>
- </object>
- <packing>
- <property name="pack-type">end</property>
- </packing>
</child>
</object>
</child>
diff --git a/data/ui/ide-layout-tab-bar.ui b/data/ui/ide-layout-tab-bar.ui
new file mode 100644
index 0000000..fb75e3b
--- /dev/null
+++ b/data/ui/ide-layout-tab-bar.ui
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.19 -->
+ <template class="IdeLayoutTabBar" parent="GtkEventBox">
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="IdeLayoutTab" id="tab">
+ <property name="margin-left">4</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="controls"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="views_list_button">
+ <property name="focus-on-click">false</property>
+ <property name="popover">views_list_popover</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">view-more-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="views_add_button">
+ <property name="action-name">perspective.new-file</property>
+ <property name="focus-on-click">false</property>
+ <property name="visible">true</property>
+ <!-- align icon with window-close button -->
+ <property name="margin-right">6</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">list-add-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkPopover" id="views_list_popover">
+ <style>
+ <class name="views-list"/>
+ </style>
+ <child>
+ <object class="EggScrolledWindow">
+ <property name="min-content-width">100</property>
+ <property name="max-content-width">300</property>
+ <property name="max-content-height">600</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkListBox" id="views_list_box">
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/data/ui/ide-layout-tab.ui b/data/ui/ide-layout-tab.ui
new file mode 100644
index 0000000..d5466ba
--- /dev/null
+++ b/data/ui/ide-layout-tab.ui
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.19 -->
+ <template class="IdeLayoutTab" parent="GtkEventBox">
+ <child>
+ <object class="GtkBox">
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">true</property>
+ <style>
+ <class name="navigation"/>
+ </style>
+ <child>
+ <object class="GtkButton" id="backward_button">
+ <property name="action-name">go-backward</property>
+ <property name="focus-on-click">false</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-previous-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="forward_button">
+ <property name="action-name">go-forward</property>
+ <property name="focus-on-click">false</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="margin-bottom">10</property>
+ <property name="margin-top">10</property>
+ <property name="orientation">vertical</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="title_menu_button">
+ <property name="hexpand">false</property>
+ <property name="focus-on-click">false</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkLabel" id="title_label">
+ <property name="ellipsize">start</property>
+ <property name="hexpand">false</property>
+ <property name="xalign">0.0</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="modified_label">
+ <property name="halign">fill</property>
+ <property name="margin-start">3</property>
+ <property name="margin-end">3</property>
+ <property name="xalign">1.0</property>
+ <property name="label">•</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="margin-start">3</property>
+ <property name="margin-end">3</property>
+ <property name="icon-name">pan-down-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <!-- expander to fill up space -->
+ <property name="hexpand">true</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <!-- spacer -->
+ <property name="visible">true</property>
+ <property name="hexpand">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="controls_container">
+ <property name="hexpand">false</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="margin-bottom">10</property>
+ <property name="margin-top">10</property>
+ <property name="orientation">vertical</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="close_button">
+ <property name="action-name">view-stack.close</property>
+ <property name="focus-on-click">false</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="margin-start">8</property>
+ <property name="margin-end">11</property>
+ <style>
+ <class name="close"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">window-close-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/libide/Makefile.am b/libide/Makefile.am
index bb19042..f2d2503 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -290,6 +290,10 @@ libide_1_0_la_SOURCES = \
ide-keybindings.h \
ide-layout-stack-actions.c \
ide-layout-stack-private.h \
+ ide-layout-tab.c \
+ ide-layout-tab.h \
+ ide-layout-tab-bar.c \
+ ide-layout-tab-bar.h \
ide-line-change-gutter-renderer.c \
ide-line-change-gutter-renderer.h \
ide-line-diagnostics-gutter-renderer.c \
diff --git a/libide/editor/ide-editor-view-actions.c b/libide/editor/ide-editor-view-actions.c
index 6f8fe84..9ca58bc 100644
--- a/libide/editor/ide-editor-view-actions.c
+++ b/libide/editor/ide-editor-view-actions.c
@@ -719,24 +719,7 @@ ide_editor_view_actions_init (IdeEditorView *self)
void
ide_editor_view_actions_update (IdeEditorView *self)
{
- GtkSourceLanguage *language;
- const gchar *lang_id = NULL;
- GActionGroup *group;
- GAction *action;
- gboolean enabled;
-
g_assert (IDE_IS_EDITOR_VIEW (self));
- group = gtk_widget_get_action_group (GTK_WIDGET (self), "view");
- if (!G_IS_SIMPLE_ACTION_GROUP (group))
- return;
-
- /* update preview sensitivity */
- language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (self->document));
- if (language)
- lang_id = gtk_source_language_get_id (language);
- enabled = ((g_strcmp0 (lang_id, "html") == 0) ||
- (g_strcmp0 (lang_id, "markdown") == 0));
- action = g_action_map_lookup_action (G_ACTION_MAP (group), "preview");
- g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enabled);
+ /* Currently a no-op */
}
diff --git a/libide/editor/ide-editor-view-private.h b/libide/editor/ide-editor-view-private.h
index d5968fd..0dde724 100644
--- a/libide/editor/ide-editor-view-private.h
+++ b/libide/editor/ide-editor-view-private.h
@@ -49,6 +49,7 @@ struct _IdeEditorView
GtkPaned *paned;
GtkProgressBar *progress_bar;
GtkMenuButton *tweak_button;
+ GtkPopover *tweak_popover;
IdeEditorTweakWidget *tweak_widget;
GtkMenuButton *goto_line_button;
EggSimplePopover *goto_line_popover;
diff --git a/libide/ide-layout-grid.c b/libide/ide-layout-grid.c
index 102a42d..6f60daa 100644
--- a/libide/ide-layout-grid.c
+++ b/libide/ide-layout-grid.c
@@ -813,6 +813,8 @@ ide_layout_grid_class_init (IdeLayoutGridClass *klass)
widget_class->grab_focus = ide_layout_grid_grab_focus;
widget_class->hierarchy_changed = ide_layout_grid_hierarchy_changed;
widget_class->size_allocate = ide_layout_grid_size_allocate;
+
+ gtk_widget_class_set_css_name (widget_class, "layoutgrid");
}
static void
diff --git a/libide/ide-layout-stack-actions.c b/libide/ide-layout-stack-actions.c
index 1c91110..062f10d 100644
--- a/libide/ide-layout-stack-actions.c
+++ b/libide/ide-layout-stack-actions.c
@@ -273,7 +273,7 @@ ide_layout_stack_actions_show_list (GSimpleAction *action,
g_assert (IDE_IS_LAYOUT_STACK (self));
- g_signal_emit_by_name (self->views_button, "activate");
+ ide_layout_tab_bar_show_list (self->tab_bar);
}
static const GActionEntry gbViewStackActions[] = {
@@ -293,12 +293,10 @@ static const GActionEntry gbViewStackActions[] = {
void
_ide_layout_stack_actions_init (IdeLayoutStack *self)
{
- GSimpleActionGroup *actions;
-
g_assert (IDE_IS_LAYOUT_STACK (self));
- actions = g_simple_action_group_new ();
- g_action_map_add_action_entries (G_ACTION_MAP (actions), gbViewStackActions,
+ self->actions = g_simple_action_group_new ();
+ g_action_map_add_action_entries (G_ACTION_MAP (self->actions), gbViewStackActions,
G_N_ELEMENTS (gbViewStackActions), self);
- gtk_widget_insert_action_group (GTK_WIDGET (self), "view-stack", G_ACTION_GROUP (actions));
+ gtk_widget_insert_action_group (GTK_WIDGET (self), "view-stack", G_ACTION_GROUP (self->actions));
}
diff --git a/libide/ide-layout-stack-private.h b/libide/ide-layout-stack-private.h
index 46cc00e..ae9205d 100644
--- a/libide/ide-layout-stack-private.h
+++ b/libide/ide-layout-stack-private.h
@@ -23,6 +23,7 @@
#include "ide-context.h"
#include "ide-back-forward-list.h"
+#include "ide-layout-tab-bar.h"
G_BEGIN_DECLS
@@ -30,6 +31,7 @@ struct _IdeLayoutStack
{
GtkBin parent_instance;
+ GSimpleActionGroup *actions;
GList *focus_history;
IdeBackForwardList *back_forward_list;
GtkGesture *swipe_gesture;
@@ -37,22 +39,10 @@ struct _IdeLayoutStack
/* Weak references */
GtkWidget *active_view;
IdeContext *context;
- GBinding *modified_binding;
- GBinding *title_binding;
/* Template references */
- GtkBox *controls;
- GtkButton *close_button;
- GtkMenuButton *document_button;
- GtkButton *go_backward;
- GtkButton *go_forward;
- GtkEventBox *header_event_box;
- GtkLabel *modified_label;
GtkStack *stack;
- GtkLabel *title_label;
- GtkListBox *views_button;
- GtkListBox *views_listbox;
- GtkPopover *views_popover;
+ IdeLayoutTabBar *tab_bar;
guint destroyed : 1;
guint focused : 1;
diff --git a/libide/ide-layout-stack.c b/libide/ide-layout-stack.c
index 9d994c0..a312ba3 100644
--- a/libide/ide-layout-stack.c
+++ b/libide/ide-layout-stack.c
@@ -31,6 +31,7 @@
#include "ide-layout-stack-actions.h"
#include "ide-layout-stack-private.h"
#include "ide-layout-stack-split.h"
+#include "ide-layout-tab-bar.h"
#include "ide-workbench.h"
G_DEFINE_TYPE (IdeLayoutStack, ide_layout_stack, GTK_TYPE_BIN)
@@ -50,108 +51,6 @@ enum {
static GParamSpec *properties [LAST_PROP];
static guint signals [LAST_SIGNAL];
-static void
-ide_layout_stack_add_list_row (IdeLayoutStack *self,
- IdeLayoutView *child)
-{
- GtkWidget *row;
- GtkWidget *label;
- GtkWidget *box;
-
- g_assert (IDE_IS_LAYOUT_STACK (self));
- g_assert (IDE_IS_LAYOUT_VIEW (child));
-
- row = g_object_new (GTK_TYPE_LIST_BOX_ROW,
- "visible", TRUE,
- NULL);
- g_object_set_data (G_OBJECT (row), "IDE_LAYOUT_VIEW", child);
-
- box = g_object_new (GTK_TYPE_BOX,
- "orientation", GTK_ORIENTATION_HORIZONTAL,
- "visible", TRUE,
- NULL);
- gtk_container_add (GTK_CONTAINER (row), box);
-
- label = g_object_new (GTK_TYPE_LABEL,
- "margin-bottom", 3,
- "margin-end", 6,
- "margin-start", 6,
- "margin-top", 3,
- "visible", TRUE,
- "xalign", 0.0f,
- NULL);
- g_object_bind_property (child, "title", label, "label", G_BINDING_SYNC_CREATE);
- gtk_container_add (GTK_CONTAINER (box), label);
-
- label = g_object_new (GTK_TYPE_LABEL,
- "visible", FALSE,
- "label", "•",
- "margin-start", 3,
- "margin-end", 3,
- NULL);
- g_object_bind_property (child, "modified", label, "visible", G_BINDING_SYNC_CREATE);
- gtk_container_add (GTK_CONTAINER (box), label);
-
- gtk_container_add (GTK_CONTAINER (self->views_listbox), row);
-}
-
-static void
-ide_layout_stack_remove_list_row (IdeLayoutStack *self,
- IdeLayoutView *child)
-{
- GList *children;
- GList *iter;
-
- g_assert (IDE_IS_LAYOUT_STACK (self));
- g_assert (IDE_IS_LAYOUT_VIEW (child));
-
- children = gtk_container_get_children (GTK_CONTAINER (self->views_listbox));
-
- for (iter = children; iter; iter = iter->next)
- {
- IdeLayoutView *view = g_object_get_data (iter->data, "IDE_LAYOUT_VIEW");
-
- if (view == child)
- {
- gtk_container_remove (GTK_CONTAINER (self->views_listbox), iter->data);
- break;
- }
- }
-
- g_list_free (children);
-}
-
-static void
-ide_layout_stack_move_top_list_row (IdeLayoutStack *self,
- IdeLayoutView *view)
-{
- GList *children;
- GList *iter;
-
- g_assert (IDE_IS_LAYOUT_STACK (self));
- g_assert (IDE_IS_LAYOUT_VIEW (view));
-
- children = gtk_container_get_children (GTK_CONTAINER (self->views_listbox));
-
- for (iter = children; iter; iter = iter->next)
- {
- GtkWidget *row = iter->data;
- IdeLayoutView *item = g_object_get_data (G_OBJECT (row), "IDE_LAYOUT_VIEW");
-
- if (item == view)
- {
- g_object_ref (row);
- gtk_container_remove (GTK_CONTAINER (self->views_listbox), row);
- gtk_list_box_prepend (self->views_listbox, row);
- gtk_list_box_select_row (self->views_listbox, GTK_LIST_BOX_ROW (row));
- g_object_unref (row);
- break;
- }
- }
-
- g_list_free (children);
-}
-
void
ide_layout_stack_add (GtkContainer *container,
GtkWidget *child)
@@ -162,15 +61,15 @@ ide_layout_stack_add (GtkContainer *container,
if (IDE_IS_LAYOUT_VIEW (child))
{
- gtk_widget_set_sensitive (GTK_WIDGET (self->close_button), TRUE);
- gtk_widget_set_sensitive (GTK_WIDGET (self->document_button), TRUE);
- gtk_widget_set_sensitive (GTK_WIDGET (self->views_button), TRUE);
+ GtkStyleContext *context;
self->focus_history = g_list_prepend (self->focus_history, child);
gtk_container_add (GTK_CONTAINER (self->stack), child);
ide_layout_view_set_back_forward_list (IDE_LAYOUT_VIEW (child), self->back_forward_list);
- ide_layout_stack_add_list_row (self, IDE_LAYOUT_VIEW (child));
gtk_stack_set_visible_child (self->stack, child);
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (self));
+ gtk_style_context_remove_class (context, "empty");
}
else
{
@@ -182,7 +81,6 @@ void
ide_layout_stack_remove (IdeLayoutStack *self,
GtkWidget *view)
{
- GtkWidget *controls;
GtkWidget *focus_after_close = NULL;
g_return_if_fail (IDE_IS_LAYOUT_STACK (self));
@@ -192,12 +90,7 @@ ide_layout_stack_remove (IdeLayoutStack *self,
if (focus_after_close != NULL)
g_object_ref (focus_after_close);
- ide_layout_stack_remove_list_row (self, IDE_LAYOUT_VIEW (view));
-
self->focus_history = g_list_remove (self->focus_history, view);
- controls = ide_layout_view_get_controls (IDE_LAYOUT_VIEW (view));
- if (controls)
- gtk_container_remove (GTK_CONTAINER (self->controls), controls);
gtk_container_remove (GTK_CONTAINER (self->stack), view);
if (focus_after_close != NULL)
@@ -207,7 +100,14 @@ ide_layout_stack_remove (IdeLayoutStack *self,
g_clear_object (&focus_after_close);
}
else
- g_signal_emit (self, signals [EMPTY], 0);
+ {
+ GtkStyleContext *context;
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (self));
+ gtk_style_context_add_class (context, "empty");
+
+ g_signal_emit (self, signals [EMPTY], 0);
+ }
}
static void
@@ -252,29 +152,6 @@ ide_layout_stack_grab_focus (GtkWidget *widget)
gtk_widget_grab_focus (visible_child);
}
-static gboolean
-ide_layout_stack_is_empty (IdeLayoutStack *self)
-{
- g_return_val_if_fail (IDE_IS_LAYOUT_STACK (self), FALSE);
-
- return (self->focus_history == NULL);
-}
-
-static void
-ide_layout_stack_real_empty (IdeLayoutStack *self)
-{
- g_assert (IDE_IS_LAYOUT_STACK (self));
-
- /* its possible for a widget to be added during "empty" emission. */
- if (ide_layout_stack_is_empty (self) && !self->destroyed)
- {
- gtk_widget_set_sensitive (GTK_WIDGET (self->close_button), FALSE);
- gtk_widget_set_sensitive (GTK_WIDGET (self->document_button), FALSE);
- gtk_widget_set_visible (GTK_WIDGET (self->modified_label), FALSE);
- gtk_widget_set_sensitive (GTK_WIDGET (self->views_button), FALSE);
- }
-}
-
#if 0
static void
navigate_to_cb (IdeLayoutStack *self,
@@ -304,6 +181,7 @@ ide_layout_stack_context_handler (GtkWidget *widget,
if (context)
{
+ GAction *action;
GList *children;
GList *iter;
@@ -325,12 +203,13 @@ ide_layout_stack_context_handler (GtkWidget *widget,
G_CONNECT_SWAPPED);
#endif
+ action = g_action_map_lookup_action (G_ACTION_MAP (self->actions), "go-backward");
g_object_bind_property (self->back_forward_list, "can-go-backward",
- self->go_backward, "sensitive",
- G_BINDING_SYNC_CREATE);
+ action, "enabled", G_BINDING_SYNC_CREATE);
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (self->actions), "go-forward");
g_object_bind_property (self->back_forward_list, "can-go-forward",
- self->go_forward, "sensitive",
- G_BINDING_SYNC_CREATE);
+ action, "enabled", G_BINDING_SYNC_CREATE);
children = gtk_container_get_children (GTK_CONTAINER (self->stack));
for (iter = children; iter; iter = iter->next)
@@ -385,27 +264,6 @@ ide_layout_stack_hierarchy_changed (GtkWidget *widget,
}
static void
-ide_layout_stack__views_listbox__row_activated_cb (IdeLayoutStack *self,
- GtkListBoxRow *row,
- GtkListBox *list_box)
-{
- IdeLayoutView *view;
-
- g_assert (IDE_IS_LAYOUT_STACK (self));
- g_assert (GTK_IS_LIST_BOX_ROW (row));
- g_assert (GTK_IS_LIST_BOX (list_box));
-
- view = g_object_get_data (G_OBJECT (row), "IDE_LAYOUT_VIEW");
-
- if (IDE_IS_LAYOUT_VIEW (view))
- {
- gtk_widget_hide (GTK_WIDGET (self->views_popover));
- ide_layout_stack_set_active_view (self, GTK_WIDGET (view));
- gtk_widget_grab_focus (GTK_WIDGET (view));
- }
-}
-
-static void
ide_layout_stack_swipe (IdeLayoutStack *self,
gdouble velocity_x,
gdouble velocity_y,
@@ -424,13 +282,13 @@ ide_layout_stack_swipe (IdeLayoutStack *self,
}
static gboolean
-ide_layout_stack__header__button_press (IdeLayoutStack *self,
- GdkEventButton *button,
- GtkEventBox *event_box)
+ide_layout_stack__tab_bar__button_press (IdeLayoutStack *self,
+ GdkEventButton *button,
+ IdeLayoutTabBar *tab_bar)
{
g_assert (IDE_IS_LAYOUT_STACK (self));
g_assert (button != NULL);
- g_assert (GTK_IS_EVENT_BOX (event_box));
+ g_assert (GTK_IS_EVENT_BOX (tab_bar));
if (button->button == GDK_BUTTON_PRIMARY)
{
@@ -455,36 +313,16 @@ static void
ide_layout_stack_constructed (GObject *object)
{
IdeLayoutStack *self = (IdeLayoutStack *)object;
- GtkPopover *popover;
- GMenu *menu;
G_OBJECT_CLASS (ide_layout_stack_parent_class)->constructed (object);
- g_signal_connect_object (self->views_listbox,
- "row-activated",
- G_CALLBACK (ide_layout_stack__views_listbox__row_activated_cb),
- self,
- G_CONNECT_SWAPPED);
-
- g_signal_connect_object (self->header_event_box,
+ g_signal_connect_object (self->tab_bar,
"button-press-event",
- G_CALLBACK (ide_layout_stack__header__button_press),
+ G_CALLBACK (ide_layout_stack__tab_bar__button_press),
self,
G_CONNECT_SWAPPED);
_ide_layout_stack_actions_init (self);
-
- menu = ide_application_get_menu_by_id (IDE_APPLICATION_DEFAULT, "ide-layout-stack-menu");
- popover = g_object_new (GTK_TYPE_POPOVER, NULL);
- gtk_popover_bind_model (popover, G_MENU_MODEL (menu), NULL);
- gtk_menu_button_set_popover (self->document_button, GTK_WIDGET (popover));
-
- /*
- * Disable things until children have been added.
- */
- gtk_widget_set_sensitive (GTK_WIDGET (self->close_button), FALSE);
- gtk_widget_set_sensitive (GTK_WIDGET (self->views_button), FALSE);
- gtk_widget_set_sensitive (GTK_WIDGET (self->document_button), FALSE);
}
static void
@@ -494,10 +332,10 @@ ide_layout_stack_finalize (GObject *object)
g_clear_pointer (&self->focus_history, g_list_free);
ide_clear_weak_pointer (&self->context);
- ide_clear_weak_pointer (&self->title_binding);
ide_clear_weak_pointer (&self->active_view);
g_clear_object (&self->back_forward_list);
g_clear_object (&self->swipe_gesture);
+ g_clear_object (&self->actions);
G_OBJECT_CLASS (ide_layout_stack_parent_class)->finalize (object);
}
@@ -572,7 +410,7 @@ ide_layout_stack_class_init (IdeLayoutStackClass *klass)
g_signal_new_class_handler ("empty",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
- G_CALLBACK (ide_layout_stack_real_empty),
+ NULL,
NULL, NULL, NULL,
G_TYPE_NONE,
0);
@@ -599,25 +437,22 @@ ide_layout_stack_class_init (IdeLayoutStackClass *klass)
gtk_widget_class_set_css_name (widget_class, "layoutstack");
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/builder/ui/ide-layout-stack.ui");
- gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, close_button);
- gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, controls);
- gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, document_button);
- gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, go_backward);
- gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, go_forward);
- gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, header_event_box);
- gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, modified_label);
gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, stack);
- gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, title_label);
- gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, views_button);
- gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, views_listbox);
- gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, views_popover);
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutStack, tab_bar);
+
+ g_type_ensure (IDE_TYPE_LAYOUT_TAB_BAR);
}
static void
ide_layout_stack_init (IdeLayoutStack *self)
{
+ GtkStyleContext *context;
+
gtk_widget_init_template (GTK_WIDGET (self));
+ context = gtk_widget_get_style_context (GTK_WIDGET (self));
+ gtk_style_context_add_class (context, "empty");
+
g_signal_connect_object (self->stack,
"notify::visible-child",
G_CALLBACK (ide_layout_stack__notify_visible_child),
@@ -666,69 +501,25 @@ ide_layout_stack_set_active_view (IdeLayoutStack *self,
if (self->active_view != active_view)
{
- if (self->active_view)
- {
- if (self->title_binding)
- g_binding_unbind (self->title_binding);
- ide_clear_weak_pointer (&self->title_binding);
- if (self->modified_binding)
- g_binding_unbind (self->modified_binding);
- ide_clear_weak_pointer (&self->modified_binding);
- gtk_label_set_label (self->title_label, NULL);
- ide_clear_weak_pointer (&self->active_view);
- gtk_widget_hide (GTK_WIDGET (self->controls));
- }
+ gtk_widget_insert_action_group (GTK_WIDGET (self), "view", NULL);
- if (active_view)
+ if (ide_set_weak_pointer (&self->active_view, active_view))
{
- GtkWidget *controls;
- GBinding *binding;
GActionGroup *group;
- ide_set_weak_pointer (&self->active_view, active_view);
if (active_view != gtk_stack_get_visible_child (self->stack))
gtk_stack_set_visible_child (self->stack, active_view);
self->focus_history = g_list_remove (self->focus_history, active_view);
self->focus_history = g_list_prepend (self->focus_history, active_view);
- binding = g_object_bind_property (active_view, "special-title",
- self->title_label, "label",
- G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
- ide_set_weak_pointer (&self->title_binding, binding);
-
- binding = g_object_bind_property (active_view, "modified",
- self->modified_label, "visible",
- G_BINDING_SYNC_CREATE);
- ide_set_weak_pointer (&self->modified_binding, binding);
-
- controls = ide_layout_view_get_controls (IDE_LAYOUT_VIEW (active_view));
-
- if (controls != NULL)
- {
- GList *children;
- GList *iter;
-
- children = gtk_container_get_children (GTK_CONTAINER (self->controls));
- for (iter = children; iter; iter = iter->next)
- gtk_container_remove (GTK_CONTAINER (self->controls), iter->data);
- g_list_free (children);
-
- gtk_container_add (GTK_CONTAINER (self->controls), controls);
- gtk_widget_show (GTK_WIDGET (self->controls));
- }
- else
- {
- gtk_widget_hide (GTK_WIDGET (self->controls));
- }
-
group = gtk_widget_get_action_group (active_view, "view");
if (group)
gtk_widget_insert_action_group (GTK_WIDGET (self), "view", group);
-
- ide_layout_stack_move_top_list_row (self, IDE_LAYOUT_VIEW (active_view));
}
+ ide_layout_tab_bar_set_view (self->tab_bar, active_view);
+
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ACTIVE_VIEW]);
}
}
diff --git a/libide/ide-layout-tab-bar.c b/libide/ide-layout-tab-bar.c
new file mode 100644
index 0000000..477d526
--- /dev/null
+++ b/libide/ide-layout-tab-bar.c
@@ -0,0 +1,403 @@
+/* ide-layout-tab-bar.c
+ *
+ * Copyright (C) 2015 Christian Hergert <chergert redhat com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "ide-layout-tab-bar"
+
+#include "ide-gtk.h"
+#include "ide-layout-stack.h"
+#include "ide-layout-tab.h"
+#include "ide-layout-tab-bar.h"
+#include "ide-layout-view.h"
+
+struct _IdeLayoutTabBar
+{
+ GtkEventBox parent_instance;
+
+ gulong set_focus_handler;
+
+ guint child_count;
+
+ IdeLayoutTab *tab;
+ GtkMenuButton *views_list_button;
+ GtkButton *views_add_button;
+ GtkStack *stack;
+ GtkListBox *views_list_box;
+ GtkPopover *views_list_popover;
+};
+
+G_DEFINE_TYPE (IdeLayoutTabBar, ide_tab_layout_bar, GTK_TYPE_EVENT_BOX)
+
+enum {
+ PROP_0,
+ PROP_STACK,
+ LAST_PROP
+};
+
+static GParamSpec *properties [LAST_PROP];
+
+static void
+ide_layout_tab_bar_close_clicked (IdeLayoutTabBar *self,
+ GtkButton *button)
+{
+ GtkWidget *row;
+ GtkWidget *view;
+
+ g_assert (IDE_IS_LAYOUT_TAB_BAR (self));
+ g_assert (GTK_IS_BUTTON (button));
+
+ row = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_LIST_BOX_ROW);
+ g_assert (row != NULL);
+
+ view = g_object_get_data (G_OBJECT (row), "IDE_LAYOUT_VIEW");
+ g_assert (IDE_IS_LAYOUT_VIEW (view));
+
+ gtk_stack_set_visible_child (self->stack, view);
+ ide_widget_action (view, "view-stack", "close", NULL);
+}
+
+static GtkWidget *
+create_row (IdeLayoutTabBar *self,
+ IdeLayoutView *view)
+{
+ GtkWidget *row;
+ GtkWidget *box;
+ GtkWidget *label;
+ GtkWidget *modified;
+ GtkWidget *expand;
+ GtkWidget *button;
+
+ g_assert (IDE_IS_LAYOUT_TAB_BAR (self));
+ g_assert (IDE_IS_LAYOUT_VIEW (view));
+
+ row = g_object_new (GTK_TYPE_LIST_BOX_ROW,
+ "visible", TRUE,
+ NULL);
+
+ box = g_object_new (GTK_TYPE_BOX,
+ "visible", TRUE,
+ NULL);
+
+ label = g_object_new (GTK_TYPE_LABEL,
+ "visible", TRUE,
+ "xalign", 0.0f,
+ NULL);
+
+ modified = g_object_new (GTK_TYPE_LABEL,
+ "margin-start", 6,
+ "label", "•",
+ NULL);
+
+ expand = g_object_new (GTK_TYPE_LABEL,
+ "hexpand", TRUE,
+ "visible", TRUE,
+ NULL);
+
+ button = g_object_new (GTK_TYPE_BUTTON,
+ "child", g_object_new (GTK_TYPE_IMAGE,
+ "visible", TRUE,
+ "icon-name", "window-close-symbolic",
+ NULL),
+ "focus-on-click", FALSE,
+ "margin-start", 18,
+ "margin-end", 6,
+ "visible", TRUE,
+ NULL);
+
+ g_signal_connect_object (button,
+ "clicked",
+ G_CALLBACK (ide_layout_tab_bar_close_clicked),
+ self,
+ G_CONNECT_SWAPPED);
+
+ gtk_container_add (GTK_CONTAINER (row), box);
+ gtk_container_add (GTK_CONTAINER (box), label);
+ gtk_container_add (GTK_CONTAINER (box), modified);
+ gtk_container_add (GTK_CONTAINER (box), expand);
+ gtk_container_add (GTK_CONTAINER (box), button);
+
+ g_object_bind_property (view, "title", label, "label", G_BINDING_SYNC_CREATE);
+ g_object_bind_property (view, "modified", modified, "visible", G_BINDING_SYNC_CREATE);
+
+ g_object_set_data (G_OBJECT (row), "IDE_LAYOUT_VIEW", view);
+
+ return row;
+}
+
+static void
+ide_layout_tab_bar_add (IdeLayoutTabBar *self,
+ IdeLayoutView *view,
+ GtkStack *stack)
+{
+ g_assert (IDE_IS_LAYOUT_TAB_BAR (self));
+ g_assert (IDE_IS_LAYOUT_VIEW (view));
+ g_assert (GTK_IS_STACK (stack));
+
+ self->child_count++;
+
+ gtk_container_add (GTK_CONTAINER (self->views_list_box), create_row (self, view));
+
+ if (self->child_count > 1)
+ gtk_widget_show (GTK_WIDGET (self->views_list_button));
+}
+
+static void
+find_row_cb (GtkWidget *widget,
+ gpointer user_data)
+{
+ struct {
+ IdeLayoutView *view;
+ GtkWidget *row;
+ } *lookup = user_data;
+ IdeLayoutView *view;
+
+ if (lookup->row != NULL)
+ return;
+
+ view = g_object_get_data (G_OBJECT (widget), "IDE_LAYOUT_VIEW");
+ g_assert (view != NULL);
+
+ if (lookup->view == view)
+ lookup->row = widget;
+}
+
+GtkWidget *
+find_row (IdeLayoutTabBar *self,
+ IdeLayoutView *view)
+{
+ struct {
+ IdeLayoutView *view;
+ GtkWidget *row;
+ } lookup = { view, NULL };
+
+ g_assert (IDE_IS_LAYOUT_TAB_BAR (self));
+ g_assert (IDE_IS_LAYOUT_VIEW (view));
+
+ gtk_container_foreach (GTK_CONTAINER (self->views_list_box), find_row_cb, &lookup);
+
+ return lookup.row;
+}
+
+static void
+ide_layout_tab_bar_remove (IdeLayoutTabBar *self,
+ IdeLayoutView *view,
+ GtkStack *stack)
+{
+ GtkWidget *row;
+
+ g_assert (IDE_IS_LAYOUT_TAB_BAR (self));
+ g_assert (IDE_IS_LAYOUT_VIEW (view));
+ g_assert (GTK_IS_STACK (stack));
+
+ row = find_row (self, view);
+
+ if (row != NULL)
+ {
+ gtk_container_remove (GTK_CONTAINER (self->views_list_box), row);
+
+ self->child_count--;
+
+ if (self->child_count <= 1)
+ gtk_widget_hide (GTK_WIDGET (self->views_list_button));
+ }
+}
+
+static void
+ide_layout_tab_bar_child_changed (IdeLayoutTabBar *self,
+ GParamSpec *pspec,
+ GtkStack *stack)
+{
+ GtkWidget *view;
+
+ g_assert (IDE_IS_LAYOUT_TAB_BAR (self));
+ g_assert (GTK_IS_STACK (stack));
+
+ view = gtk_stack_get_visible_child (stack);
+
+ if (IDE_IS_LAYOUT_VIEW (view))
+ {
+ GtkWidget *row = find_row (self, IDE_LAYOUT_VIEW (view));
+
+ if (row != NULL)
+ gtk_list_box_select_row (self->views_list_box, GTK_LIST_BOX_ROW (row));
+ }
+}
+
+static void
+ide_layout_tab_bar_row_selected (IdeLayoutTabBar *self,
+ GtkListBoxRow *row,
+ GtkListBox *list)
+{
+ GtkWidget *view;
+
+ g_assert (IDE_IS_LAYOUT_TAB_BAR (self));
+ g_assert (GTK_IS_LIST_BOX (list));
+ g_assert (!row || GTK_IS_LIST_BOX_ROW (row));
+
+ if (row == NULL)
+ return;
+
+ view = g_object_get_data (G_OBJECT (row), "IDE_LAYOUT_VIEW");
+
+ if (view != NULL)
+ {
+ if (gtk_stack_get_visible_child (self->stack) != view)
+ gtk_stack_set_visible_child (self->stack, view);
+ }
+}
+
+static void
+ide_layout_tab_bar_popover_closed (IdeLayoutTabBar *self,
+ GtkPopover *popover)
+{
+ GtkWidget *child;
+
+ g_assert (IDE_IS_LAYOUT_TAB_BAR (self));
+
+ child = gtk_stack_get_visible_child (self->stack);
+ if (child != NULL)
+ gtk_widget_grab_focus (child);
+}
+
+static void
+ide_layout_tab_bar_set_stack (IdeLayoutTabBar *self,
+ GtkStack *stack)
+{
+ g_assert (IDE_IS_LAYOUT_TAB_BAR (self));
+ g_assert (GTK_IS_STACK (stack));
+
+ self->stack = stack;
+
+ g_signal_connect_object (stack,
+ "add",
+ G_CALLBACK (ide_layout_tab_bar_add),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (stack,
+ "remove",
+ G_CALLBACK (ide_layout_tab_bar_remove),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (stack,
+ "notify::visible-child",
+ G_CALLBACK (ide_layout_tab_bar_child_changed),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+ide_layout_tab_bar_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdeLayoutTabBar *self = IDE_LAYOUT_TAB_BAR(object);
+
+ switch (prop_id)
+ {
+ case PROP_STACK:
+ g_value_set_object (value, self->stack);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+ide_layout_tab_bar_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ IdeLayoutTabBar *self = IDE_LAYOUT_TAB_BAR(object);
+
+ switch (prop_id)
+ {
+ case PROP_STACK:
+ ide_layout_tab_bar_set_stack (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+ide_tab_layout_bar_class_init (IdeLayoutTabBarClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = ide_layout_tab_bar_get_property;
+ object_class->set_property = ide_layout_tab_bar_set_property;
+
+ properties [PROP_STACK] =
+ g_param_spec_object ("stack",
+ "stack",
+ "stack",
+ GTK_TYPE_STACK,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+
+ gtk_widget_class_set_css_name (widget_class, "layouttabbar");
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/builder/ui/ide-layout-tab-bar.ui");
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutTabBar, tab);
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutTabBar, views_add_button);
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutTabBar, views_list_button);
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutTabBar, views_list_box);
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutTabBar, views_list_popover);
+}
+
+static void
+ide_tab_layout_bar_init (IdeLayoutTabBar *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ g_signal_connect_object (self->views_list_box,
+ "row-selected",
+ G_CALLBACK (ide_layout_tab_bar_row_selected),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->views_list_popover,
+ "closed",
+ G_CALLBACK (ide_layout_tab_bar_popover_closed),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+void
+ide_layout_tab_bar_set_view (IdeLayoutTabBar *self,
+ GtkWidget *view)
+{
+ g_return_if_fail (IDE_IS_LAYOUT_TAB_BAR (self));
+ g_return_if_fail (!view || IDE_IS_LAYOUT_VIEW (view));
+
+ ide_layout_tab_set_view (self->tab, view);
+}
+
+void
+ide_layout_tab_bar_show_list (IdeLayoutTabBar *self)
+{
+ g_return_if_fail (IDE_IS_LAYOUT_TAB_BAR (self));
+
+ gtk_widget_activate (GTK_WIDGET (self->views_list_button));
+}
diff --git a/libide/ide-layout-tab-bar.h b/libide/ide-layout-tab-bar.h
new file mode 100644
index 0000000..0a98a7f
--- /dev/null
+++ b/libide/ide-layout-tab-bar.h
@@ -0,0 +1,36 @@
+/* ide-layout-tab-bar.h
+ *
+ * Copyright (C) 2015 Christian Hergert <chergert redhat com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_LAYOUT_TAB_BAR_H
+#define IDE_LAYOUT_TAB_BAR_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_LAYOUT_TAB_BAR (ide_tab_layout_bar_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeLayoutTabBar, ide_tab_layout_bar, IDE, LAYOUT_TAB_BAR, GtkEventBox)
+
+void ide_layout_tab_bar_set_view (IdeLayoutTabBar *self,
+ GtkWidget *view);
+void ide_layout_tab_bar_show_list (IdeLayoutTabBar *self);
+
+G_END_DECLS
+
+#endif /* IDE_LAYOUT_TAB_BAR_H */
diff --git a/libide/ide-layout-tab.c b/libide/ide-layout-tab.c
new file mode 100644
index 0000000..45c91b6
--- /dev/null
+++ b/libide/ide-layout-tab.c
@@ -0,0 +1,243 @@
+/* ide-layout-tab.c
+ *
+ * Copyright (C) 2015 Christian Hergert <chergert redhat com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "ide-layout-tab"
+
+#include "ide-application.h"
+#include "ide-layout-view.h"
+#include "ide-layout-tab.h"
+#include "ide-macros.h"
+
+struct _IdeLayoutTab
+{
+ GtkEventBox parent_instance;
+
+ IdeLayoutView *view;
+ GBinding *modified_binding;
+ GBinding *title_binding;
+
+ GtkWidget *backward_button;
+ GtkWidget *controls_container;
+ GtkWidget *close_button;
+ GtkWidget *forward_button;
+ GtkWidget *modified_label;
+ GtkWidget *title_menu_button;
+ GtkWidget *title_label;
+};
+
+G_DEFINE_TYPE (IdeLayoutTab, ide_layout_tab, GTK_TYPE_EVENT_BOX)
+
+enum {
+ PROP_0,
+ PROP_VIEW,
+ LAST_PROP
+};
+
+static GParamSpec *properties [LAST_PROP];
+
+static void
+ide_layout_tab_connect (IdeLayoutTab *self)
+{
+ GtkWidget *controls;
+ GBinding *binding;
+
+ g_assert (IDE_IS_LAYOUT_TAB (self));
+
+ binding = g_object_bind_property (self->view, "special-title",
+ self->title_label, "label",
+ G_BINDING_SYNC_CREATE);
+ ide_set_weak_pointer (&self->title_binding, binding);
+
+ binding = g_object_bind_property (self->view, "modified",
+ self->modified_label, "visible",
+ G_BINDING_SYNC_CREATE);
+ ide_set_weak_pointer (&self->modified_binding, binding);
+
+ controls = ide_layout_view_get_controls (self->view);
+ if (controls != NULL)
+ gtk_container_add (GTK_CONTAINER (self->controls_container), controls);
+
+ gtk_widget_set_visible (self->close_button, TRUE);
+}
+
+static void
+ide_layout_tab_remove_control (GtkWidget *widget,
+ gpointer user_data)
+{
+ IdeLayoutTab *self = user_data;
+
+ g_assert (IDE_IS_LAYOUT_TAB (self));
+
+ gtk_container_remove (GTK_CONTAINER (self->controls_container), widget);
+}
+
+static void
+ide_layout_tab_disconnect (IdeLayoutTab *self)
+{
+ g_assert (IDE_IS_LAYOUT_TAB (self));
+
+ gtk_container_foreach (GTK_CONTAINER (self->controls_container),
+ ide_layout_tab_remove_control,
+ self);
+
+ if (self->title_binding)
+ {
+ g_binding_unbind (self->title_binding);
+ ide_clear_weak_pointer (&self->title_binding);
+ }
+
+ gtk_label_set_text (GTK_LABEL (self->title_label), NULL);
+
+ if (self->modified_binding)
+ {
+ g_binding_unbind (self->modified_binding);
+ ide_clear_weak_pointer (&self->modified_binding);
+ }
+
+ gtk_widget_set_visible (self->modified_label, FALSE);
+ gtk_widget_set_visible (self->close_button, FALSE);
+}
+
+GtkWidget *
+ide_layout_tab_get_view (IdeLayoutTab *self)
+{
+ g_return_val_if_fail (IDE_IS_LAYOUT_TAB (self), NULL);
+
+ return GTK_WIDGET (self->view);
+}
+
+void
+ide_layout_tab_set_view (IdeLayoutTab *self,
+ GtkWidget *view)
+{
+ g_return_if_fail (IDE_IS_LAYOUT_TAB (self));
+ g_return_if_fail (!view || IDE_IS_LAYOUT_VIEW (view));
+
+ if (view != (GtkWidget *)self->view)
+ {
+ if (self->view != NULL)
+ {
+ ide_layout_tab_disconnect (self);
+ self->view = NULL;
+ }
+
+ if (view != NULL)
+ {
+ self->view = IDE_LAYOUT_VIEW (view);
+ ide_layout_tab_connect (self);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_VIEW]);
+ }
+}
+
+static void
+ide_layout_tab_destroy (GtkWidget *widget)
+{
+ IdeLayoutTab *self = (IdeLayoutTab *)widget;
+
+ if (self->view != NULL)
+ {
+ ide_layout_tab_disconnect (self);
+ self->view = NULL;
+ }
+
+ GTK_WIDGET_CLASS (ide_layout_tab_parent_class)->destroy (widget);
+}
+
+static void
+ide_layout_tab_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdeLayoutTab *self = IDE_LAYOUT_TAB (object);
+
+ switch (prop_id)
+ {
+ case PROP_VIEW:
+ g_value_set_object (value, ide_layout_tab_get_view (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_layout_tab_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ IdeLayoutTab *self = IDE_LAYOUT_TAB (object);
+
+ switch (prop_id)
+ {
+ case PROP_VIEW:
+ ide_layout_tab_set_view (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_layout_tab_class_init (IdeLayoutTabClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = ide_layout_tab_get_property;
+ object_class->set_property = ide_layout_tab_set_property;
+
+ widget_class->destroy = ide_layout_tab_destroy;
+
+ properties [PROP_VIEW] =
+ g_param_spec_object ("view",
+ "View",
+ "The view to be represented by the tab",
+ IDE_TYPE_LAYOUT_VIEW,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+
+ gtk_widget_class_set_css_name (widget_class, "layouttab");
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/builder/ui/ide-layout-tab.ui");
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutTab, backward_button);
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutTab, close_button);
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutTab, controls_container);
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutTab, forward_button);
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutTab, modified_label);
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutTab, title_label);
+ gtk_widget_class_bind_template_child (widget_class, IdeLayoutTab, title_menu_button);
+}
+
+static void
+ide_layout_tab_init (IdeLayoutTab *self)
+{
+ GMenu *menu;
+ GtkWidget *popover;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ menu = ide_application_get_menu_by_id (IDE_APPLICATION_DEFAULT, "ide-layout-stack-menu");
+ popover = gtk_popover_new_from_model (self->title_menu_button, G_MENU_MODEL (menu));
+ gtk_menu_button_set_popover (GTK_MENU_BUTTON (self->title_menu_button), popover);
+}
diff --git a/libide/ide-layout-tab.h b/libide/ide-layout-tab.h
new file mode 100644
index 0000000..8179213
--- /dev/null
+++ b/libide/ide-layout-tab.h
@@ -0,0 +1,35 @@
+/* ide-layout-tab.h
+ *
+ * Copyright (C) 2015 Christian Hergert <chergert redhat com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_LAYOUT_TAB_H
+#define IDE_LAYOUT_TAB_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_LAYOUT_TAB (ide_layout_tab_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeLayoutTab, ide_layout_tab, IDE, LAYOUT_TAB, GtkEventBox)
+
+void ide_layout_tab_set_view (IdeLayoutTab *self,
+ GtkWidget *view);
+
+G_END_DECLS
+
+#endif /* IDE_LAYOUT_TAB_H */
diff --git a/libide/resources/libide.gresource.xml b/libide/resources/libide.gresource.xml
index 7260e24..6d9bc9e 100644
--- a/libide/resources/libide.gresource.xml
+++ b/libide/resources/libide.gresource.xml
@@ -48,6 +48,8 @@
<file alias="ide-greeter-perspective.ui">../../data/ui/ide-greeter-perspective.ui</file>
<file alias="ide-greeter-project-row.ui">../../data/ui/ide-greeter-project-row.ui</file>
<file alias="ide-layout.ui">../../data/ui/ide-layout.ui</file>
+ <file alias="ide-layout-tab.ui">../../data/ui/ide-layout-tab.ui</file>
+ <file alias="ide-layout-tab-bar.ui">../../data/ui/ide-layout-tab-bar.ui</file>
<file alias="ide-layout-pane.ui">../../data/ui/ide-layout-pane.ui</file>
<file alias="ide-layout-stack.ui">../../data/ui/ide-layout-stack.ui</file>
<file alias="ide-omni-search-group.ui">../../data/ui/ide-omni-search-group.ui</file>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]