Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
World
Design Tooling
Contrast
Commits
36ca234b
Commit
36ca234b
authored
Mar 17, 2020
by
Bilal Elmoussaoui
Browse files
subclass window
parent
24d4921e
Changes
6
Hide whitespace changes
Inline
Side-by-side
data/meson.build
View file @
36ca234b
...
...
@@ -79,7 +79,6 @@ ui_config.set('version', meson.project_version() + version_suffix)
ui_config
.
set
(
'name-prefix'
,
name_prefix
)
ui_preconfigured_files
=
files
(
'resources/ui/about_dialog.ui.in'
,
'resources/ui/window.ui.in'
,
)
ui_dependencies
=
[]
foreach
ui_file
:
ui_preconfigured_files
...
...
data/resources.gresource.xml
View file @
36ca234b
...
...
@@ -3,7 +3,6 @@
<gresource
prefix=
"/org/gnome/design/Contrast/"
>
<file
compressed=
"true"
preprocess=
"xml-stripblanks"
>
about_dialog.ui
</file>
<file
compressed=
"true"
preprocess=
"xml-stripblanks"
alias=
"shortcuts.ui"
>
resources/ui/shortcuts.ui
</file>
<file
compressed=
"true"
preprocess=
"xml-stripblanks"
>
window.ui
</file>
<file
compressed=
"true"
alias=
"style.css"
>
resources/style.css
</file>
</gresource>
<gresource
prefix=
"/org/gnome/design/Contrast/icons"
>
...
...
data/resources/ui/window.ui.in
deleted
100644 → 0
View file @
24d4921e
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires
lib=
"gtk+"
version=
"3.20"
/>
<object
class=
"GtkPopoverMenu"
id=
"popover"
>
<property
name=
"can_focus"
>
False
</property>
<child>
<object
class=
"GtkBox"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"border_width"
>
10
</property>
<property
name=
"orientation"
>
vertical
</property>
<child>
<object
class=
"GtkModelButton"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"receives_default"
>
False
</property>
<property
name=
"action_name"
>
win.show-help-overlay
</property>
<property
name=
"text"
translatable=
"yes"
>
_Keyboard Shortcuts
</property>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
4
</property>
</packing>
</child>
<child>
<object
class=
"GtkModelButton"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"receives_default"
>
False
</property>
<property
name=
"action_name"
>
app.about
</property>
<property
name=
"text"
translatable=
"yes"
>
_About Contrast
</property>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
7
</property>
</packing>
</child>
</object>
<packing>
<property
name=
"submenu"
>
main
</property>
<property
name=
"position"
>
1
</property>
</packing>
</child>
</object>
<object
class=
"GtkApplicationWindow"
id=
"window_widget"
>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"title"
translatable=
"yes"
>
@name-prefix@Contrast
</property>
<property
name=
"default_width"
>
650
</property>
<property
name=
"default_height"
>
500
</property>
<property
name=
"icon_name"
>
@app-id@
</property>
<child
type=
"titlebar"
>
<object
class=
"HdyHeaderBar"
id=
"headerbar"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"title"
translatable=
"yes"
>
@name-prefix@Contrast
</property>
<property
name=
"show_close_button"
>
True
</property>
<property
name=
"centering_policy"
>
HDY_CENTERING_POLICY_LOOSE
</property>
<child>
<object
class=
"GtkMenuButton"
id=
"appmenu_button"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
True
</property>
<property
name=
"receives_default"
>
True
</property>
<property
name=
"popover"
>
popover
</property>
<child>
<object
class=
"GtkImage"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"icon_name"
>
open-menu-symbolic
</property>
</object>
</child>
</object>
<packing>
<property
name=
"pack_type"
>
end
</property>
</packing>
</child>
</object>
</child>
<child>
<placeholder/>
</child>
</object>
</interface>
src/application.rs
View file @
36ca234b
...
...
@@ -14,7 +14,7 @@ pub enum Action {
pub
struct
Application
{
app
:
gtk
::
Application
,
window
:
Rc
<
Window
>
,
window
:
Window
,
provider
:
gtk
::
CssProvider
,
receiver
:
RefCell
<
Option
<
Receiver
<
Action
>>>
,
}
...
...
@@ -24,7 +24,7 @@ impl Application {
let
app
=
gtk
::
Application
::
new
(
Some
(
config
::
APP_ID
),
gio
::
ApplicationFlags
::
FLAGS_NONE
)
.unwrap
();
let
(
sender
,
r
)
=
glib
::
MainContext
::
channel
(
glib
::
PRIORITY_DEFAULT
);
let
receiver
=
RefCell
::
new
(
Some
(
r
));
let
window
=
Window
::
new
(
sender
);
let
window
=
Window
::
new
(
sender
,
&
app
);
let
provider
=
gtk
::
CssProvider
::
new
();
let
application
=
Rc
::
new
(
Self
{
app
,
window
,
provider
,
receiver
});
...
...
@@ -48,7 +48,7 @@ impl Application {
action!
(
self
.app
,
"about"
,
clone!
(
@
weak
self
.window
.widget
as
window
=>
move
|
_
,
_
|
{
clone!
(
@
weak
self
.window
as
window
=>
move
|
_
,
_
|
{
let
builder
=
gtk
::
Builder
::
new_from_resource
(
"/org/gnome/design/Contrast/about_dialog.ui"
);
get_widget!
(
builder
,
gtk
::
AboutDialog
,
about_dialog
);
about_dialog
.set_transient_for
(
Some
(
&
window
));
...
...
@@ -65,7 +65,7 @@ impl Application {
}
fn
setup_signals
(
&
self
)
{
self
.app
.connect_activate
(
clone!
(
@
weak
self
.window
.widget
as
window
=>
move
|
app
|
{
self
.app
.connect_activate
(
clone!
(
@
weak
self
.window
as
window
=>
move
|
app
|
{
window
.set_application
(
Some
(
app
));
app
.add_window
(
&
window
);
window
.present
();
...
...
src/window.rs
View file @
36ca234b
...
...
@@ -8,70 +8,161 @@ use super::window_state::WindowState;
use
gettextrs
::
gettext
;
use
gio
::
prelude
::
*
;
use
glib
::
subclass
;
use
glib
::
subclass
::
prelude
::
*
;
use
glib
::
translate
::
*
;
use
glib
::
ObjectExt
;
use
gtk
::
prelude
::
*
;
use
gtk
::
subclass
::
prelude
::{
ApplicationWindowImpl
,
BinImpl
,
ContainerImpl
,
WidgetImpl
,
WindowImpl
};
use
libhandy
::
HeaderBarExt
;
use
std
::{
cell
::
RefCell
,
rc
::
Rc
};
pub
struct
Window
{
pub
widget
:
gtk
::
ApplicationWindow
,
builder
:
gtk
::
Builder
,
pub
struct
WindowPrivate
{
fg_entry
:
ColourEntry
,
bg_entry
:
ColourEntry
,
reverse_btn
:
gtk
::
Button
,
pub
state
:
Rc
<
RefCell
<
WindowState
>>
,
pub
levelbar
:
RefCell
<
ContrastLevelBar
>
,
state
:
Rc
<
RefCell
<
WindowState
>>
,
levelbar
:
RefCell
<
ContrastLevelBar
>
,
pub
preview
:
ContrastPreview
,
sender
:
glib
::
Sender
<
Action
>
,
sender
:
RefCell
<
Option
<
glib
::
Sender
<
Action
>
>>
,
}
impl
Window
{
pub
fn
new
(
sender
:
glib
::
Sender
<
Action
>
)
->
Rc
<
Self
>
{
let
settings
=
gio
::
Settings
::
new
(
APP_ID
);
let
builder
=
gtk
::
Builder
::
new_from_resource
(
"/org/gnome/design/Contrast/window.ui"
);
get_widget!
(
builder
,
gtk
::
ApplicationWindow
,
window_widget
);
impl
ObjectSubclass
for
WindowPrivate
{
const
NAME
:
&
'static
str
=
"Window"
;
type
ParentType
=
gtk
::
ApplicationWindow
;
type
Instance
=
subclass
::
simple
::
InstanceStruct
<
Self
>
;
type
Class
=
subclass
::
simple
::
ClassStruct
<
Self
>
;
glib_object_subclass!
();
fn
new
()
->
Self
{
let
settings
=
gio
::
Settings
::
new
(
APP_ID
);
let
bg_entry
=
ColourEntry
::
new
(
&
gettext
(
"Background Colour"
));
let
fg_entry
=
ColourEntry
::
new
(
&
gettext
(
"Foreground Colour"
));
let
reverse_btn
=
gtk
::
Button
::
new
();
let
state
=
Rc
::
new
(
RefCell
::
new
(
WindowState
::
init
(
settings
)));
let
levelbar
=
RefCell
::
new
(
ContrastLevelBar
::
new
());
let
preview
=
ContrastPreview
::
new
();
let
window
=
Rc
::
new
(
Window
{
widget
:
window_widget
,
builder
,
fg_entry
,
Self
{
bg_entry
,
reverse_btn
,
state
,
fg_entry
,
levelbar
,
preview
,
sender
,
});
state
,
sender
:
RefCell
::
new
(
None
),
}
}
}
impl
ObjectImpl
for
WindowPrivate
{
glib_object_impl!
();
fn
constructed
(
&
self
,
obj
:
&
glib
::
Object
)
{
self
.parent_constructed
(
obj
);
let
self_
=
obj
.downcast_ref
::
<
Window
>
()
.unwrap
();
if
PROFILE
==
"Devel"
{
self_
.get_style_context
()
.add_class
(
"devel"
);
}
let
builder
=
gtk
::
Builder
::
new_from_resource
(
"/org/gnome/design/Contrast/shortcuts.ui"
);
get_widget!
(
builder
,
gtk
::
ShortcutsWindow
,
shortcuts_dialog
);
self_
.set_help_overlay
(
Some
(
&
shortcuts_dialog
));
let
container
=
gtk
::
Box
::
new
(
gtk
::
Orientation
::
Vertical
,
0
);
container
.get_style_context
()
.add_class
(
"main-container"
);
container
.set_valign
(
gtk
::
Align
::
Center
);
self
.fg_entry
.get_entry
()
.get_style_context
()
.add_class
(
"fg-entry"
);
self
.bg_entry
.get_entry
()
.get_style_context
()
.add_class
(
"bg-entry"
);
let
reverse_btn
=
gtk
::
Button
::
new
();
reverse_btn
.set_halign
(
gtk
::
Align
::
Center
);
reverse_btn
.set_action_name
(
Some
(
"window.reverse-colors"
));
let
reverse_img
=
gtk
::
Image
::
new_from_icon_name
(
Some
(
"network-transmit-receive-symbolic"
),
gtk
::
IconSize
::
Button
);
reverse_btn
.set_image
(
Some
(
&
reverse_img
));
let
entries_container
=
gtk
::
Box
::
new
(
gtk
::
Orientation
::
Horizontal
,
0
);
entries_container
.pack_start
(
&
self
.bg_entry
,
false
,
false
,
6
);
entries_container
.pack_start
(
&
reverse_btn
,
false
,
false
,
6
);
entries_container
.pack_start
(
&
self
.fg_entry
,
false
,
false
,
6
);
entries_container
.set_halign
(
gtk
::
Align
::
Center
);
let
headerbar
=
libhandy
::
HeaderBar
::
new
();
headerbar
.set_show_close_button
(
true
);
headerbar
.set_title
(
Some
(
&
gettext
(
"Contrast"
)));
headerbar
.set_custom_title
(
Some
(
&
entries_container
));
self_
.set_titlebar
(
Some
(
&
headerbar
));
let
primary_menu
=
gio
::
Menu
::
new
();
primary_menu
.append
(
Some
(
&
gettext
(
"_Keyboard Shortcuts"
)),
Some
(
"win.show-help-overlay"
));
primary_menu
.append
(
Some
(
&
gettext
(
"_About Contrast"
)),
Some
(
"app.about"
));
let
primary_btn
=
gtk
::
MenuButton
::
new
();
let
primary_popover
=
gtk
::
Popover
::
new_from_model
(
Some
(
&
primary_btn
),
&
primary_menu
);
let
primary_img
=
gtk
::
Image
::
new_from_icon_name
(
Some
(
"open-menu-symbolic"
),
gtk
::
IconSize
::
Button
);
primary_btn
.add
(
&
primary_img
);
primary_btn
.set_popover
(
Some
(
&
primary_popover
));
headerbar
.pack_end
(
&
primary_btn
);
container
.pack_start
(
&
self
.preview
,
true
,
true
,
12
);
container
.pack_start
(
&
self
.levelbar
.borrow
()
.widget
,
true
,
true
,
12
);
self_
.add
(
&
container
);
// Restore state
self
.state
.borrow_mut
()
.load_into
(
self_
,
&
self
.bg_entry
,
&
self
.fg_entry
);
self_
.show_all
();
}
}
impl
WidgetImpl
for
WindowPrivate
{}
impl
ContainerImpl
for
WindowPrivate
{}
impl
BinImpl
for
WindowPrivate
{}
impl
WindowImpl
for
WindowPrivate
{}
impl
ApplicationWindowImpl
for
WindowPrivate
{}
window
.setup_widgets
();
window
.setup_signals
(
window
.clone
());
glib_wrapper!
{
pub
struct
Window
(
Object
<
subclass
::
simple
::
InstanceStruct
<
WindowPrivate
>
,
subclass
::
simple
::
ClassStruct
<
WindowPrivate
>
,
SwApplicationWindowClass
>
)
@
extends
gtk
::
Widget
,
gtk
::
Container
,
gtk
::
Bin
,
gtk
::
Window
,
gtk
::
ApplicationWindow
;
match
fn
{
get_type
=>
||
WindowPrivate
::
get_type
()
.to_glib
(),
}
}
impl
Window
{
pub
fn
new
(
sender
:
glib
::
Sender
<
Action
>
,
app
:
&
gtk
::
Application
)
->
Self
{
let
window
=
glib
::
Object
::
new
(
Window
::
static_type
(),
&
[(
"application"
,
app
)])
.unwrap
()
.downcast
::
<
Window
>
()
.unwrap
();
window
.setup_signals
(
sender
);
window
}
fn
colour_changed
(
&
self
,
bg_colour
:
String
,
fg_colour
:
String
)
{
let
bg_rgba
=
self
.state
.borrow_mut
()
.set_bg_colour
(
Some
(
&
bg_colour
));
let
fg_rgba
=
self
.state
.borrow_mut
()
.set_fg_colour
(
Some
(
&
fg_colour
));
let
self_
=
WindowPrivate
::
from_instance
(
self
);
let
bg_rgba
=
self_
.state
.borrow_mut
()
.set_bg_colour
(
Some
(
&
bg_colour
));
let
fg_rgba
=
self_
.state
.borrow_mut
()
.set_fg_colour
(
Some
(
&
fg_colour
));
let
contrast_level
=
colour
::
calc_contrast_level
(
&
bg_rgba
,
&
fg_rgba
);
self
.levelbar
.borrow_mut
()
.set_contrast_level
(
contrast_level
);
self
.preview
.set_contrast_level
(
contrast_level
);
colour
::
compile_styles
(
&
self
.sender
,
fg_rgba
,
bg_rgba
);
self_
.levelbar
.borrow_mut
()
.set_contrast_level
(
contrast_level
);
self_
.preview
.set_contrast_level
(
contrast_level
);
if
let
Some
(
sender
)
=
self_
.sender
.borrow
()
.clone
()
{
colour
::
compile_styles
(
&
sender
,
fg_rgba
,
bg_rgba
);
}
}
fn
setup_signals
(
&
self
,
window
:
Rc
<
Self
>
)
{
fn
setup_signals
(
&
self
,
sender
:
glib
::
Sender
<
Action
>
)
{
let
self_
=
WindowPrivate
::
from_instance
(
self
);
self_
.sender
.borrow_mut
()
.replace
(
sender
);
// save window state on delete event
self
.
widget
.
connect_delete_event
(
clone!
(
@
strong
self
.state
as
state
=>
move
|
window
,
_
|
{
self
.connect_delete_event
(
clone!
(
@
strong
self
_
.state
as
state
,
@
strong
self
as
window
=>
move
|
_
,
_
|
{
if
let
Err
(
err
)
=
state
.borrow_mut
()
.dump
(
&
window
)
{
warn!
(
"Failed to save window state {}"
,
err
);
}
...
...
@@ -79,22 +170,23 @@ impl Window {
}));
let
on_entry_changed
=
clone!
(
@
strong
self
.fg_entry
as
fg_entry
,
@
strong
self
.bg_entry
as
bg_entry
,
@
weak
window
=>
move
|
_entry
:
&
gtk
::
Entry
|
{
@
strong
self
_
.fg_entry
as
fg_entry
,
@
strong
self
_
.bg_entry
as
bg_entry
,
@
strong
self
as
window
=>
move
|
_entry
:
&
gtk
::
Entry
|
{
let
fg_colour
=
fg_entry
.get_text
();
let
bg_colour
=
bg_entry
.get_text
();
window
.colour_changed
(
bg_colour
,
fg_colour
);
});
let
bg_handle
=
self
.bg_entry
.get_entry
()
.connect_changed
(
on_entry_changed
.clone
());
let
fg_handle
=
self
.fg_entry
.get_entry
()
.connect_changed
(
on_entry_changed
);
let
bg_handle
=
self
_
.bg_entry
.get_entry
()
.connect_changed
(
on_entry_changed
.clone
());
let
fg_handle
=
self
_
.fg_entry
.get_entry
()
.connect_changed
(
on_entry_changed
);
let
actions
=
gio
::
SimpleActionGroup
::
new
();
action!
(
actions
,
"reverse-colors"
,
clone!
(
@
strong
self
.fg_entry
as
fg_entry
,
@
strong
self
.bg_entry
as
bg_entry
=>
move
|
_
,
_
|
{
clone!
(
@
strong
self_
.fg_entry
as
fg_entry
,
@
strong
self_
.bg_entry
as
bg_entry
,
@
strong
self
as
window
=>
move
|
_
,
_
|
{
fg_entry
.get_entry
()
.block_signal
(
&
fg_handle
);
bg_entry
.get_entry
()
.block_signal
(
&
bg_handle
);
let
fg_colour
=
fg_entry
.get_text
();
...
...
@@ -108,45 +200,8 @@ impl Window {
window
.colour_changed
(
fg_colour
,
bg_colour
);
})
);
self
.widget
.insert_action_group
(
"window"
,
Some
(
&
actions
));
}
fn
setup_widgets
(
&
self
)
{
if
PROFILE
==
"Devel"
{
self
.widget
.get_style_context
()
.add_class
(
"devel"
);
}
let
builder
=
gtk
::
Builder
::
new_from_resource
(
"/org/gnome/design/Contrast/shortcuts.ui"
);
get_widget!
(
builder
,
gtk
::
ShortcutsWindow
,
shortcuts_dialog
);
self
.widget
.set_help_overlay
(
Some
(
&
shortcuts_dialog
));
let
container
=
gtk
::
Box
::
new
(
gtk
::
Orientation
::
Vertical
,
0
);
container
.get_style_context
()
.add_class
(
"main-container"
);
container
.set_valign
(
gtk
::
Align
::
Center
);
self
.fg_entry
.get_entry
()
.get_style_context
()
.add_class
(
"fg-entry"
);
self
.bg_entry
.get_entry
()
.get_style_context
()
.add_class
(
"bg-entry"
);
self
.reverse_btn
.set_halign
(
gtk
::
Align
::
Center
);
self
.reverse_btn
.set_action_name
(
Some
(
"window.reverse-colors"
));
let
reverse_img
=
gtk
::
Image
::
new_from_icon_name
(
Some
(
"network-transmit-receive-symbolic"
),
gtk
::
IconSize
::
Button
);
self
.reverse_btn
.set_image
(
Some
(
&
reverse_img
));
self
.insert_action_group
(
"window"
,
Some
(
&
actions
));
let
entries_container
=
gtk
::
Box
::
new
(
gtk
::
Orientation
::
Horizontal
,
0
);
entries_container
.pack_start
(
&
self
.bg_entry
,
false
,
false
,
6
);
entries_container
.pack_start
(
&
self
.reverse_btn
,
false
,
false
,
6
);
entries_container
.pack_start
(
&
self
.fg_entry
,
false
,
false
,
6
);
entries_container
.set_halign
(
gtk
::
Align
::
Center
);
get_widget!
(
self
.builder
,
libhandy
::
HeaderBar
,
headerbar
);
headerbar
.set_custom_title
(
Some
(
&
entries_container
));
container
.pack_start
(
&
self
.preview
,
true
,
true
,
12
);
container
.pack_start
(
&
self
.levelbar
.borrow
()
.widget
,
true
,
true
,
12
);
self
.widget
.add
(
&
container
);
// Restore state
self
.state
.borrow_mut
()
.load_into
(
&
self
.widget
,
&
self
.bg_entry
,
&
self
.fg_entry
);
self
.colour_changed
(
self
.bg_entry
.get_text
(),
self
.fg_entry
.get_text
());
self
.widget
.show_all
();
self
.colour_changed
(
self_
.bg_entry
.get_text
(),
self_
.fg_entry
.get_text
());
}
}
src/window_state.rs
View file @
36ca234b
use
super
::
colour
;
use
super
::
colour_entry
::
ColourEntry
;
use
super
::
window
::
Window
;
use
gio
::
prelude
::
SettingsExt
;
use
gtk
::
prelude
::
GtkWindowExt
;
use
rand
::
Rng
;
...
...
@@ -67,7 +68,7 @@ impl WindowState {
}
}
pub
fn
load_into
(
&
self
,
window
:
&
gtk
::
Application
Window
,
bg_entry
:
&
ColourEntry
,
fg_entry
:
&
ColourEntry
)
{
pub
fn
load_into
(
&
self
,
window
:
&
Window
,
bg_entry
:
&
ColourEntry
,
fg_entry
:
&
ColourEntry
)
{
window
.resize
(
550
,
250
);
if
self
.x
>
-
1
&&
self
.y
>
-
1
{
...
...
@@ -107,7 +108,7 @@ impl WindowState {
self
.fg_colour
}
pub
fn
dump
(
&
self
,
window
:
&
gtk
::
Application
Window
)
->
Result
<
(),
failure
::
Error
>
{
pub
fn
dump
(
&
self
,
window
:
&
Window
)
->
Result
<
(),
failure
::
Error
>
{
let
position
=
window
.get_position
();
self
.settings
.set_boolean
(
"is-maximized"
,
window
.is_maximized
())
?
;
self
.settings
.set_int
(
"window-x"
,
position
.0
)
?
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment