mittens_ui 0.0.7 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +5 -2
- data/LICENSE +21 -0
- data/README.md +78 -21
- data/examples/app.rb +101 -8
- data/examples/assets/gnome_logo.png +0 -0
- data/examples/assets/mittens_ui_preview.gif +0 -0
- data/examples/contacts.rb +80 -0
- data/examples/file_menu_example.rb +52 -0
- data/examples/notify_example.rb +19 -0
- data/lib/mittens_ui.rb +40 -67
- data/lib/mittens_ui/alert.rb +32 -0
- data/lib/mittens_ui/assets/icon.png +0 -0
- data/lib/mittens_ui/assets/mittens_ui_preview.gif +0 -0
- data/lib/mittens_ui/button.rb +40 -0
- data/lib/mittens_ui/checkbox.rb +24 -0
- data/lib/mittens_ui/core.rb +34 -0
- data/lib/mittens_ui/file_menu.rb +83 -0
- data/lib/mittens_ui/file_picker.rb +29 -0
- data/lib/mittens_ui/grid.rb +29 -0
- data/lib/mittens_ui/hbox.rb +56 -0
- data/lib/mittens_ui/header_bar.rb +46 -0
- data/lib/mittens_ui/helpers.rb +41 -0
- data/lib/mittens_ui/image.rb +46 -0
- data/lib/mittens_ui/label.rb +19 -0
- data/lib/mittens_ui/listbox.rb +47 -0
- data/lib/mittens_ui/loader.rb +33 -0
- data/lib/mittens_ui/notify.rb +61 -0
- data/lib/mittens_ui/slider.rb +32 -0
- data/lib/mittens_ui/switch.rb +36 -0
- data/lib/mittens_ui/table_view.rb +179 -0
- data/lib/mittens_ui/textbox.rb +53 -0
- data/lib/mittens_ui/version.rb +1 -1
- data/lib/mittens_ui/web_link.rb +22 -0
- data/mittens_ui.gemspec +3 -3
- data/notes/dev_setup.txt +14 -0
- metadata +37 -16
- data/examples/brightness_controller.rb +0 -64
- data/lib/mittens_ui/layouts/box.rb +0 -38
- data/lib/mittens_ui/layouts/grid.rb +0 -31
- data/lib/mittens_ui/widgets/alert.rb +0 -33
- data/lib/mittens_ui/widgets/button.rb +0 -34
- data/lib/mittens_ui/widgets/label.rb +0 -41
- data/lib/mittens_ui/widgets/listbox.rb +0 -45
- data/lib/mittens_ui/widgets/slider.rb +0 -32
- data/lib/mittens_ui/widgets/switch.rb +0 -57
- data/lib/mittens_ui/widgets/textbox.rb +0 -25
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require '../lib/mittens_ui'
|
|
2
|
+
|
|
3
|
+
app_options = {
|
|
4
|
+
name: "notify_example",
|
|
5
|
+
title: "Notify This",
|
|
6
|
+
height: 615,
|
|
7
|
+
width: 570,
|
|
8
|
+
can_resize: true
|
|
9
|
+
}.freeze
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
MittensUi::Application.Window(app_options) do
|
|
13
|
+
btn = MittensUi::Button.new(title: "Notify Me")
|
|
14
|
+
btn.render
|
|
15
|
+
|
|
16
|
+
btn.click do
|
|
17
|
+
MittensUi::Notify.new("Updated!").render
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/mittens_ui.rb
CHANGED
|
@@ -1,74 +1,65 @@
|
|
|
1
1
|
require "mittens_ui/version"
|
|
2
|
-
require "mittens_ui/
|
|
3
|
-
require "mittens_ui/
|
|
4
|
-
require "mittens_ui/
|
|
5
|
-
require "mittens_ui/
|
|
6
|
-
require "mittens_ui/
|
|
7
|
-
require "mittens_ui/
|
|
8
|
-
require "mittens_ui/
|
|
2
|
+
require "mittens_ui/alert"
|
|
3
|
+
require "mittens_ui/label"
|
|
4
|
+
require "mittens_ui/button"
|
|
5
|
+
require "mittens_ui/textbox"
|
|
6
|
+
require "mittens_ui/listbox"
|
|
7
|
+
require "mittens_ui/slider"
|
|
8
|
+
require "mittens_ui/switch"
|
|
9
|
+
require "mittens_ui/image"
|
|
10
|
+
require "mittens_ui/checkbox"
|
|
11
|
+
require "mittens_ui/web_link"
|
|
12
|
+
require "mittens_ui/table_view"
|
|
13
|
+
require "mittens_ui/loader"
|
|
14
|
+
require "mittens_ui/header_bar"
|
|
15
|
+
require "mittens_ui/file_picker"
|
|
16
|
+
require "mittens_ui/file_menu"
|
|
17
|
+
require "mittens_ui/hbox"
|
|
18
|
+
require "mittens_ui/notify"
|
|
9
19
|
|
|
10
20
|
require "gtk3"
|
|
11
21
|
|
|
12
22
|
module MittensUi
|
|
13
|
-
|
|
14
23
|
class Error < StandardError; end
|
|
15
24
|
|
|
16
|
-
def self.Switch(options = {})
|
|
17
|
-
MittensUi::Widgets::Switch.new(options)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def self.Slider(options = {})
|
|
21
|
-
MittensUi::Widgets::Slider.new(options)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def self.ListBox(options = {})
|
|
25
|
-
MittensUi::Widgets::ListBox.new(options)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def self.Alert(message, options = {})
|
|
29
|
-
MittensUi::Widgets::Alert.new(message, options)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def self.Label(text, options = {})
|
|
33
|
-
MittensUi::Widgets::Label.new(text, options)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def self.Textbox(options = {})
|
|
37
|
-
MittensUi::Widgets::Textbox.new(options)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def self.Button(options = {})
|
|
41
|
-
MittensUi::Widgets::Button.new(options)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def self.RemoveWidget(widget)
|
|
45
|
-
widget.remove
|
|
46
|
-
end
|
|
47
|
-
|
|
48
25
|
class Application
|
|
49
26
|
class << self
|
|
50
|
-
def Window(options = {}, &block)
|
|
51
|
-
init_gtk_application(options, block)
|
|
27
|
+
def Window(options = {}, &block)
|
|
28
|
+
init_gtk_application(options, &block)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def exit(&block)
|
|
32
|
+
begin
|
|
33
|
+
yield if block_given?
|
|
34
|
+
Kernel.exit(0)
|
|
35
|
+
rescue => _error
|
|
36
|
+
Kernel.exit(1)
|
|
37
|
+
end
|
|
52
38
|
end
|
|
53
|
-
|
|
54
|
-
private
|
|
39
|
+
|
|
40
|
+
private
|
|
55
41
|
|
|
56
42
|
def set_process_name(name)
|
|
57
|
-
# Doesn't work in MacOS Activity Monitor or Windows Task Manager. It shows up as "Ruby".
|
|
58
43
|
Process.setproctitle(name)
|
|
59
44
|
$PROGRAM_NAME = name
|
|
45
|
+
$0 = name
|
|
60
46
|
end
|
|
61
47
|
|
|
62
|
-
def init_gtk_application(options, block)
|
|
48
|
+
def init_gtk_application(options, &block)
|
|
63
49
|
app_name = options[:name].nil? ? "mittens_ui_app" : options[:name]
|
|
64
50
|
height = options[:height].nil? ? 600 : options[:height]
|
|
65
51
|
width = options[:width].nil? ? 400 : options[:width]
|
|
66
52
|
title = options[:title].nil? ? "Mittens App" : options[:title]
|
|
67
53
|
can_resize = options[:can_resize].nil? ? true : options[:can_resize]
|
|
68
54
|
|
|
55
|
+
app_assets_path = File.join(File.expand_path(File.dirname(__FILE__)), "mittens_ui", "assets") + "/"
|
|
56
|
+
default_icon = app_assets_path + "icon.png"
|
|
57
|
+
|
|
58
|
+
app_icon = options[:icon].nil? ? default_icon : options[:icon]
|
|
59
|
+
|
|
69
60
|
set_process_name(app_name)
|
|
70
61
|
|
|
71
|
-
gtk_app_name = "org.
|
|
62
|
+
gtk_app_name = "org.mittens_ui.#{app_name}"
|
|
72
63
|
|
|
73
64
|
app = Gtk::Application.new(gtk_app_name, :flags_none)
|
|
74
65
|
|
|
@@ -78,10 +69,11 @@ module MittensUi
|
|
|
78
69
|
$vertical_box = Gtk::Box.new(:vertical, 10)
|
|
79
70
|
scrolled_window.add($vertical_box)
|
|
80
71
|
$app_window.add(scrolled_window)
|
|
81
|
-
|
|
72
|
+
yield($app_window, $vertical_box)
|
|
82
73
|
$app_window.set_size_request(width, height)
|
|
83
74
|
$app_window.set_title(title)
|
|
84
75
|
$app_window.set_resizable(can_resize)
|
|
76
|
+
$app_window.set_icon_from_file(app_icon)
|
|
85
77
|
$app_window.show_all
|
|
86
78
|
end
|
|
87
79
|
|
|
@@ -89,23 +81,4 @@ module MittensUi
|
|
|
89
81
|
end
|
|
90
82
|
end
|
|
91
83
|
end
|
|
92
|
-
|
|
93
|
-
class Job
|
|
94
|
-
attr_reader :name, :status
|
|
95
|
-
|
|
96
|
-
def initialize(name)
|
|
97
|
-
@name = name
|
|
98
|
-
@status = nil
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def run(&block)
|
|
102
|
-
job_t = Thread.new { |_t| yield }
|
|
103
|
-
set_status(job_t)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
private
|
|
107
|
-
def set_status(thread)
|
|
108
|
-
@status = thread.status
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
84
|
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module MittensUi
|
|
2
|
+
class Alert
|
|
3
|
+
def initialize(message, options={})
|
|
4
|
+
dialog_options = {
|
|
5
|
+
title: options[:title] || "Alert",
|
|
6
|
+
parent: $app_window,
|
|
7
|
+
flags: [:modal, :destroy_with_parent],
|
|
8
|
+
:buttons => [[Gtk::Stock::OK, :none]]
|
|
9
|
+
}.freeze
|
|
10
|
+
|
|
11
|
+
@alert_dialog = Gtk::Dialog.new(dialog_options)
|
|
12
|
+
@alert_dialog.set_transient_for($app_window)
|
|
13
|
+
@alert_dialog.set_default_width(420)
|
|
14
|
+
@alert_dialog.set_default_height(200)
|
|
15
|
+
@alert_dialog.set_modal(true)
|
|
16
|
+
@alert_dialog.set_resizable(false)
|
|
17
|
+
|
|
18
|
+
message_label = Gtk::Label.new(message)
|
|
19
|
+
message_label.set_margin_top(36)
|
|
20
|
+
|
|
21
|
+
dialog_box = @alert_dialog.content_area
|
|
22
|
+
dialog_box.add(message_label)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def render
|
|
26
|
+
@alert_dialog.show_all
|
|
27
|
+
response = @alert_dialog.run
|
|
28
|
+
response == :none ? @alert_dialog.destroy : @alert_dialog.destroy
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require_relative "./core"
|
|
2
|
+
require "mittens_ui/helpers"
|
|
3
|
+
|
|
4
|
+
module MittensUi
|
|
5
|
+
class Button < Core
|
|
6
|
+
include Helpers
|
|
7
|
+
|
|
8
|
+
def initialize(options={})
|
|
9
|
+
button_title = options[:title] || "Button"
|
|
10
|
+
|
|
11
|
+
icon_type = options[:icon] || nil
|
|
12
|
+
|
|
13
|
+
if icon_type
|
|
14
|
+
image = Gtk::Image.new(icon_name: icon_map[icon_type], size: @button)
|
|
15
|
+
@button = Gtk::Button.new
|
|
16
|
+
@button.add(image)
|
|
17
|
+
else
|
|
18
|
+
@button = Gtk::Button.new(label: button_title)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
super(@button, options)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def enable(answer)
|
|
25
|
+
@button.set_sensitive(answer)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def click
|
|
29
|
+
@button.signal_connect("clicked") do |button_widget|
|
|
30
|
+
yield(button_widget)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def render
|
|
35
|
+
$vertical_box.pack_start(@button)
|
|
36
|
+
return self
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require_relative "./core"
|
|
2
|
+
|
|
3
|
+
module MittensUi
|
|
4
|
+
class Checkbox < Core
|
|
5
|
+
attr_accessor :value
|
|
6
|
+
|
|
7
|
+
def initialize(options={})
|
|
8
|
+
label = options[:label] || "Checkbox"
|
|
9
|
+
|
|
10
|
+
@value = nil
|
|
11
|
+
@checkbox = Gtk::CheckButton.new(label)
|
|
12
|
+
|
|
13
|
+
$vertical_box.pack_start(@checkbox)
|
|
14
|
+
|
|
15
|
+
super(@checkbox, options)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def toggle
|
|
19
|
+
@checkbox.signal_connect "toggled" do
|
|
20
|
+
yield
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require "mittens_ui/helpers"
|
|
2
|
+
|
|
3
|
+
module MittensUi
|
|
4
|
+
class Core
|
|
5
|
+
include Helpers
|
|
6
|
+
|
|
7
|
+
attr_reader :core_widget
|
|
8
|
+
|
|
9
|
+
# All MittenUi::Widgets::* classes should inherit from this base class.
|
|
10
|
+
|
|
11
|
+
def initialize(widget, options={})
|
|
12
|
+
# core_widget is the Raw Gtk::Widget*
|
|
13
|
+
@core_widget = widget
|
|
14
|
+
set_margin_from_opts_for(@core_widget, options)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def show
|
|
18
|
+
@core_widget.show_all
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def hidden?
|
|
22
|
+
@core_widget.visible?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def hide
|
|
26
|
+
return if @core_widget.nil?
|
|
27
|
+
@core_widget.hide
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def remove
|
|
31
|
+
$vertical_box.remove(@core_widget)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require_relative "./core"
|
|
2
|
+
|
|
3
|
+
module MittensUi
|
|
4
|
+
class FileMenu < Core
|
|
5
|
+
def initialize(menu_items, options = {})
|
|
6
|
+
@menu_items = menu_items
|
|
7
|
+
|
|
8
|
+
@menu_bar = Gtk::MenuBar.new
|
|
9
|
+
|
|
10
|
+
# menu_name => menu_item(gtk)
|
|
11
|
+
@raw_menu_items = {}
|
|
12
|
+
|
|
13
|
+
associate_menu_items
|
|
14
|
+
|
|
15
|
+
create_menu_methods
|
|
16
|
+
|
|
17
|
+
super(@menu_bar, options)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def render
|
|
21
|
+
$vertical_box.pack_start(@menu_bar)
|
|
22
|
+
return self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def create_menu_methods
|
|
28
|
+
@raw_menu_items.each do |menu_label, menu_item|
|
|
29
|
+
menu_label = menu_label.downcase.gsub(/ /, "_").to_sym
|
|
30
|
+
|
|
31
|
+
define_singleton_method(menu_label) do |&blk|
|
|
32
|
+
menu_item.signal_connect("activate") do
|
|
33
|
+
blk.call(self)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def associate_menu_items
|
|
40
|
+
@menu_items.each do |root_menu_label, menu_item_data|
|
|
41
|
+
root_menu = Gtk::Menu.new
|
|
42
|
+
|
|
43
|
+
root_menu_item = Gtk::MenuItem.new(label: root_menu_label.to_s)
|
|
44
|
+
root_menu_item.set_submenu(root_menu)
|
|
45
|
+
|
|
46
|
+
next unless menu_item_data.is_a?(Hash)
|
|
47
|
+
|
|
48
|
+
menu_item_data.each do |sub_menus_key, sub_menus_item_data|
|
|
49
|
+
next unless sub_menus_key.to_sym == :sub_menus
|
|
50
|
+
sub_menus_item_data.each do |sub_menu_data|
|
|
51
|
+
sub_menu_data.is_a?(String) ? create_root_menu(sub_menu_data.to_s, root_menu) : nil
|
|
52
|
+
sub_menu_data.is_a?(Hash) ? create_sub_menu(sub_menu_data, root_menu) : nil
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
@menu_bar.append(root_menu_item)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def create_sub_menu(hsh, root_menu)
|
|
61
|
+
hsh.each do |sub_menu_label, sub_menu_data|
|
|
62
|
+
sub_menu = Gtk::Menu.new
|
|
63
|
+
sub_menu_item = Gtk::MenuItem.new(label: sub_menu_label.to_s)
|
|
64
|
+
sub_menu_item.set_submenu(sub_menu)
|
|
65
|
+
root_menu.append(sub_menu_item)
|
|
66
|
+
|
|
67
|
+
if sub_menu_data.is_a?(Array)
|
|
68
|
+
sub_menu_data.each do |label|
|
|
69
|
+
nested_sub_item = Gtk::MenuItem.new(label: label.to_s)
|
|
70
|
+
sub_menu.append(nested_sub_item)
|
|
71
|
+
@raw_menu_items[label.to_s] = nested_sub_item
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def create_root_menu(label, root_menu)
|
|
78
|
+
menu_item = Gtk::MenuItem.new(label: label)
|
|
79
|
+
root_menu.append(menu_item)
|
|
80
|
+
@raw_menu_items[label] = menu_item
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module MittensUi
|
|
2
|
+
class FilePicker
|
|
3
|
+
attr_reader :path
|
|
4
|
+
|
|
5
|
+
def initialize(options={})
|
|
6
|
+
@path = ""
|
|
7
|
+
|
|
8
|
+
dialog_options = {
|
|
9
|
+
title: "Select File",
|
|
10
|
+
parent: $app_window,
|
|
11
|
+
action: options[:action] || :open,
|
|
12
|
+
buttons: [
|
|
13
|
+
[Gtk::Stock::OPEN, Gtk::ResponseType::ACCEPT],
|
|
14
|
+
[Gtk::Stock::CANCEL, Gtk::ResponseType::CANCEL]
|
|
15
|
+
]
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
@dialog = Gtk::FileChooserDialog.new(dialog_options)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def render
|
|
22
|
+
if @dialog.run == :accept
|
|
23
|
+
@path = @dialog.filename
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
@dialog.destroy
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module MittensUi
|
|
2
|
+
class Grid
|
|
3
|
+
def initialize(window, &block)
|
|
4
|
+
@grid = Gtk::Grid.new
|
|
5
|
+
yield(self)
|
|
6
|
+
window.add_child(@grid)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def attach(widget, options)
|
|
10
|
+
grid_height = options[:height]
|
|
11
|
+
grid_width = options[:width]
|
|
12
|
+
grid_top = options[:top]
|
|
13
|
+
grid_left = options[:left]
|
|
14
|
+
|
|
15
|
+
# Place widget next to each other in the direction determined by the “orientation” property
|
|
16
|
+
# defaults to :horizontal.
|
|
17
|
+
if options.size >= 1
|
|
18
|
+
@grid.add(widget)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
unless options[:attach_to].nil?
|
|
22
|
+
return
|
|
23
|
+
@grid.attach_next_to()
|
|
24
|
+
else
|
|
25
|
+
@grid.attach(widget, grid_left, grid_top, grid_width, grid_height)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|