gtk3 3.0.5 → 3.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/gtk3/rb-gtk3-cell-layout.c +42 -0
- data/ext/gtk3/rb-gtk3-private.h +3 -0
- data/ext/gtk3/rb-gtk3-tree-model.c +77 -0
- data/ext/gtk3/rb-gtk3-tree-view.c +42 -0
- data/ext/gtk3/rb-gtk3.c +33 -0
- data/lib/gtk3/builder.rb +54 -11
- data/lib/gtk3/container.rb +13 -0
- data/lib/gtk3/deprecated.rb +4 -4
- data/lib/gtk3/loader.rb +2 -0
- data/lib/gtk3/show-uri.rb +34 -0
- data/lib/gtk3/stock-item.rb +36 -0
- data/lib/gtk3/tree-iter.rb +3 -1
- data/sample/gtk-demo/TODO +1 -1
- data/sample/gtk-demo/alias_cursor.png +0 -0
- data/sample/gtk-demo/all_scroll_cursor.png +0 -0
- data/sample/gtk-demo/application.ui +11 -18
- data/sample/gtk-demo/brick.png +0 -0
- data/sample/gtk-demo/brick2.png +0 -0
- data/sample/gtk-demo/cell_cursor.png +0 -0
- data/sample/gtk-demo/col_resize_cursor.png +0 -0
- data/sample/gtk-demo/copy_cursor.png +0 -0
- data/sample/gtk-demo/crosshair_cursor.png +0 -0
- data/sample/gtk-demo/css_accordion.css +1 -2
- data/sample/gtk-demo/css_basics.css +1 -1
- data/sample/gtk-demo/css_multiplebgs.css +136 -0
- data/sample/gtk-demo/css_pixbufs.css +76 -0
- data/sample/gtk-demo/css_shadows.css +44 -0
- data/sample/gtk-demo/cssview.css +41 -0
- data/sample/gtk-demo/decor1.png +0 -0
- data/sample/gtk-demo/decor2.png +0 -0
- data/sample/gtk-demo/default_cursor.png +0 -0
- data/sample/gtk-demo/demo.gresource.xml +216 -0
- data/sample/gtk-demo/demo.ui +285 -241
- data/sample/gtk-demo/e_resize_cursor.png +0 -0
- data/sample/gtk-demo/ew_resize_cursor.png +0 -0
- data/sample/gtk-demo/filtermodel.ui +195 -0
- data/sample/gtk-demo/font-features.ui +966 -0
- data/sample/gtk-demo/glarea-fragment.glsl +9 -0
- data/sample/gtk-demo/glarea-vertex.glsl +8 -0
- data/sample/gtk-demo/grab_cursor.png +0 -0
- data/sample/gtk-demo/grabbing_cursor.png +0 -0
- data/sample/gtk-demo/hand_cursor.png +0 -0
- data/sample/gtk-demo/help_cursor.png +0 -0
- data/sample/gtk-demo/listbox.ui +332 -0
- data/sample/gtk-demo/main.rb +132 -313
- data/sample/gtk-demo/main.ui +190 -0
- data/sample/gtk-demo/markup.txt +16 -0
- data/sample/gtk-demo/menus.ui +1 -1
- data/sample/gtk-demo/messages.txt +388 -0
- data/sample/gtk-demo/modelbutton.ui +162 -0
- data/sample/gtk-demo/move_cursor.png +0 -0
- data/sample/gtk-demo/n_resize_cursor.png +0 -0
- data/sample/gtk-demo/ne_resize_cursor.png +0 -0
- data/sample/gtk-demo/nesw_resize_cursor.png +0 -0
- data/sample/gtk-demo/no_drop_cursor.png +0 -0
- data/sample/gtk-demo/none_cursor.png +0 -0
- data/sample/gtk-demo/not_allowed_cursor.png +0 -0
- data/sample/gtk-demo/ns_resize_cursor.png +0 -0
- data/sample/gtk-demo/nw_resize_cursor.png +0 -0
- data/sample/gtk-demo/nwse_resize_cursor.png +0 -0
- data/sample/gtk-demo/org.gtk.Demo.gschema.xml +17 -0
- data/sample/gtk-demo/pointer_cursor.png +0 -0
- data/sample/gtk-demo/popover.ui +94 -0
- data/sample/gtk-demo/progress_cursor.png +0 -0
- data/sample/gtk-demo/reset.css +0 -1
- data/sample/gtk-demo/revealer.ui +177 -0
- data/sample/gtk-demo/row_resize_cursor.png +0 -0
- data/sample/gtk-demo/s_resize_cursor.png +0 -0
- data/sample/gtk-demo/scale.ui +117 -0
- data/sample/gtk-demo/se_resize_cursor.png +0 -0
- data/sample/gtk-demo/spinbutton.ui +194 -0
- data/sample/gtk-demo/stack.ui +72 -0
- data/sample/gtk-demo/sw_resize_cursor.png +0 -0
- data/sample/gtk-demo/text_cursor.png +0 -0
- data/sample/gtk-demo/theming.ui +102 -147
- data/sample/gtk-demo/vertical_text_cursor.png +0 -0
- data/sample/gtk-demo/w_resize_cursor.png +0 -0
- data/sample/gtk-demo/wait_cursor.png +0 -0
- data/sample/gtk-demo/zoom_in_cursor.png +0 -0
- data/sample/gtk-demo/zoom_out_cursor.png +0 -0
- data/sample/tutorial/README.md +415 -0
- data/test/run-test.rb +1 -1
- data/test/test-gtk-builder.rb +108 -30
- data/test/test-gtk-cell-layout.rb +6 -0
- metadata +80 -16
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/sample/tutorial/README.md
CHANGED
@@ -521,3 +521,418 @@ In this line, given that `self` is `ExampleAppWindow` the usage of `stack` is a
|
|
521
521
|
https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.8
|
522
522
|
|
523
523
|
* exampleapp4/exampleapp.rb
|
524
|
+
|
525
|
+
An application menu is shown by GNOME shell at the top of the screen. It is meant to collect infrequently used actions that affect the whole application.
|
526
|
+
Just like the window template, we specify our application menu in a ui file, and add it as a resource to our binary.
|
527
|
+
|
528
|
+
#### Adding the menu interface
|
529
|
+
|
530
|
+
* app-menu.ui
|
531
|
+
```xml
|
532
|
+
<?xml version="1.0"?>
|
533
|
+
<interface>
|
534
|
+
<!-- interface-requires gtk+ 3.0 -->
|
535
|
+
<menu id="appmenu">
|
536
|
+
<section>
|
537
|
+
<item>
|
538
|
+
<attribute name="label" translatable="yes">_Preferences</attribute>
|
539
|
+
<attribute name="action">app.preferences</attribute>
|
540
|
+
</item>
|
541
|
+
</section>
|
542
|
+
<section>
|
543
|
+
<item>
|
544
|
+
<attribute name="label" translatable="yes">_Quit</attribute>
|
545
|
+
<attribute name="action">app.quit</attribute>
|
546
|
+
</item>
|
547
|
+
</section>
|
548
|
+
</menu>
|
549
|
+
</interface>
|
550
|
+
```
|
551
|
+
|
552
|
+
This menu interface is loaded and added to our application with :
|
553
|
+
|
554
|
+
```ruby
|
555
|
+
builder = Gtk::Builder.new(:resource => "/org/gtk/exampleapp/app-menu.ui")
|
556
|
+
app_menu = builder.get_object("appmenu")
|
557
|
+
application.set_app_menu(app_menu)
|
558
|
+
```
|
559
|
+
|
560
|
+
With this, our application has a menu with two items that we can show when clicking on the application icon in the Gnome shell.
|
561
|
+
|
562
|
+
#### Linking menu items to actions.
|
563
|
+
|
564
|
+
All the actions initialization should be done during the "startup" step, which is guaranteed to be called once for each primary application instance.
|
565
|
+
|
566
|
+
The "quit" item in the menu is implemented with this:
|
567
|
+
|
568
|
+
```xml
|
569
|
+
<section>
|
570
|
+
<item>
|
571
|
+
<attribute name="label" translatable="yes">_Quit</attribute>
|
572
|
+
<attribute name="action">app.quit</attribute>
|
573
|
+
</item>
|
574
|
+
</section>
|
575
|
+
```
|
576
|
+
|
577
|
+
Then we just have to create an `Gio::SimpleAction` named "quit" and configure it in order to quit the application when this action is triggered.
|
578
|
+
|
579
|
+
```ruby
|
580
|
+
action = Gio::SimpleAction.new("quit")
|
581
|
+
action.signal_connect("activate") do |_action, parameter|
|
582
|
+
application.quit
|
583
|
+
end
|
584
|
+
application.add_action(action)
|
585
|
+
|
586
|
+
```
|
587
|
+
|
588
|
+
#### Add accelerators for action.
|
589
|
+
|
590
|
+
An accelerator is just a keys combination that acts as a shortcut for an action.
|
591
|
+
|
592
|
+
```ruby
|
593
|
+
quit_accels = ["<Ctrl>Q"]
|
594
|
+
action = Gio::SimpleAction.new("quit")
|
595
|
+
action.signal_connect("activate") do |_action, parameter|
|
596
|
+
application.quit
|
597
|
+
end
|
598
|
+
application.add_action(action)
|
599
|
+
application.set_accels_for_action("app.quit", quit_accels)
|
600
|
+
```
|
601
|
+
|
602
|
+
### A preferences dialog
|
603
|
+
https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.9
|
604
|
+
|
605
|
+
### Define and store settings for an application with gschemas
|
606
|
+
* exampleapp5/exampleapp.rb
|
607
|
+
|
608
|
+
A typical application will have a some preferences that should be remembered from one run to the next. Even for our simple example application, we may want to change the font that is used for the content.
|
609
|
+
We are going to use `Gio::Settings` to store our preferences. `Gio::Settings` requires a schema that describes our settings:
|
610
|
+
|
611
|
+
```xml
|
612
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
613
|
+
<schemalist>
|
614
|
+
<schema path="/org/gtk/exampleapp/" id="org.gtk.exampleapp">
|
615
|
+
<key name="font" type="s">
|
616
|
+
<default>'Monospace 12'</default>
|
617
|
+
<summary>Font</summary>
|
618
|
+
<description>The font to be used for content.</description>
|
619
|
+
</key>
|
620
|
+
<key name="transition" type="s">
|
621
|
+
<choices>
|
622
|
+
<choice value='none'/>
|
623
|
+
<choice value='crossfade'/>
|
624
|
+
<choice value='slide-left-right'/>
|
625
|
+
</choices>
|
626
|
+
<default>'none'</default>
|
627
|
+
<summary>Transition</summary>
|
628
|
+
<description>The transition to use when switching tabs.</description>
|
629
|
+
</key>
|
630
|
+
</schema>
|
631
|
+
</schemalist>
|
632
|
+
```
|
633
|
+
|
634
|
+
Before we can make use of this schema in our application, we need to compile it into the binary form that `Gio::Settings` expects.
|
635
|
+
|
636
|
+
```ruby
|
637
|
+
system("glib-compile-schemas", data_path)
|
638
|
+
```
|
639
|
+
In this command, the tool *glib-compile-schemas* searches all files with a name that ends with *.gschema.xml* and compiles it into a binary file called *gschemas.compiled*.
|
640
|
+
|
641
|
+
This binary file can be loaded and our custom schema installed at the begining of our script with:
|
642
|
+
|
643
|
+
```ruby
|
644
|
+
Gio::SettingsSchemaSource.new(data_path,
|
645
|
+
Gio::SettingsSchemaSource.default,
|
646
|
+
false)
|
647
|
+
|
648
|
+
```
|
649
|
+
This is the corresponding method to the function [g_settings_schema_source_new_from_directory](https://developer.gnome.org/gio/stable/gio-GSettingsSchema-GSettingsSchemaSource.html#g-settings-schema-source-new-from-directory).
|
650
|
+
|
651
|
+
As an alternative, our schema can just be loaded by using the `GSETTINGS_SCHEMA_DIR` environment variable.
|
652
|
+
|
653
|
+
```ruby
|
654
|
+
ENV["GSETTINGS_SCHEMA_DIR"] = data_path
|
655
|
+
```
|
656
|
+
More informations on the use of gschemas can be found [here](https://developer.gnome.org/gio/stable/gio-GSettingsSchema-GSettingsSchemaSource.html)
|
657
|
+
|
658
|
+
Next, we need to connect our settings to the widgets that they are supposed to control. One convenient way to do this is to use `Gio::Settings` bind functionality to bind settings keys to object properties, as we do here for the transition setting. The `Gio::Settings#bind` is the ruby method for the [g_settings_bind](https://developer.gnome.org/gio/stable/GSettings.html#g-settings-bind) fonction of `gio`
|
659
|
+
|
660
|
+
```ruby
|
661
|
+
class ExampleAppWindow < Gtk::ApplicationWindow
|
662
|
+
type_register
|
663
|
+
class << self
|
664
|
+
def init
|
665
|
+
set_template(:resource => "/org/gtk/exampleapp/window.ui")
|
666
|
+
bind_template_child("stack")
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
670
|
+
def initialize(application)
|
671
|
+
super(:application => application)
|
672
|
+
settings = Gio::Settings.new("org.gtk.exampleapp")
|
673
|
+
settings.bind("transition",
|
674
|
+
stack,
|
675
|
+
"transition-type",
|
676
|
+
Gio::SettingsBindFlags::DEFAULT)
|
677
|
+
end
|
678
|
+
...
|
679
|
+
```
|
680
|
+
|
681
|
+
#### Configure the settings with a dialog window
|
682
|
+
|
683
|
+
* exampleapp6/exampleapp.rb
|
684
|
+
|
685
|
+
The code to connect the font setting is a little more involved, since there is no simple object property that it corresponds to, so we are not going to go into that here.
|
686
|
+
At this point, the application will already react if you change one of the settings, e.g. using the gsettings commandline tool. Of course, we expect the application to provide a preference dialog for these. So lets do that now. Our preference dialog will be a subclass of `Gtk::Dialog`, and we'll use the same techniques that we've already seen: templates, bind child widget name to method, settings bindings.
|
687
|
+
|
688
|
+
Lets start with the template.
|
689
|
+
|
690
|
+
```xml
|
691
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
692
|
+
<interface>
|
693
|
+
<!-- interface-requires gtk+ 3.8 -->
|
694
|
+
<template class="ExampleAppPrefs" parent="GtkDialog">
|
695
|
+
<property name="title" translatable="yes">Preferences</property>
|
696
|
+
<property name="resizable">False</property>
|
697
|
+
<property name="modal">True</property>
|
698
|
+
<child internal-child="vbox">
|
699
|
+
<object class="GtkBox" id="vbox">
|
700
|
+
<child>
|
701
|
+
<object class="GtkGrid" id="grid">
|
702
|
+
<property name="visible">True</property>
|
703
|
+
<property name="margin">6</property>
|
704
|
+
<property name="row-spacing">12</property>
|
705
|
+
<property name="column-spacing">6</property>
|
706
|
+
<child>
|
707
|
+
<object class="GtkLabel" id="fontlabel">
|
708
|
+
<property name="visible">True</property>
|
709
|
+
<property name="label">_Font:</property>
|
710
|
+
<property name="use-underline">True</property>
|
711
|
+
<property name="mnemonic-widget">font</property>
|
712
|
+
<property name="xalign">1</property>
|
713
|
+
</object>
|
714
|
+
<packing>
|
715
|
+
<property name="left-attach">0</property>
|
716
|
+
<property name="top-attach">0</property>
|
717
|
+
</packing>
|
718
|
+
</child>
|
719
|
+
<child>
|
720
|
+
<object class="GtkFontButton" id="font">
|
721
|
+
<property name="visible">True</property>
|
722
|
+
</object>
|
723
|
+
<packing>
|
724
|
+
<property name="left-attach">1</property>
|
725
|
+
<property name="top-attach">0</property>
|
726
|
+
</packing>
|
727
|
+
</child>
|
728
|
+
<child>
|
729
|
+
<object class="GtkLabel" id="transitionlabel">
|
730
|
+
<property name="visible">True</property>
|
731
|
+
<property name="label">_Transition:</property>
|
732
|
+
<property name="use-underline">True</property>
|
733
|
+
<property name="mnemonic-widget">transition</property>
|
734
|
+
<property name="xalign">1</property>
|
735
|
+
</object>
|
736
|
+
<packing>
|
737
|
+
<property name="left-attach">0</property>
|
738
|
+
<property name="top-attach">1</property>
|
739
|
+
</packing>
|
740
|
+
</child>
|
741
|
+
<child>
|
742
|
+
<object class="GtkComboBoxText" id="transition">
|
743
|
+
<property name="visible">True</property>
|
744
|
+
<items>
|
745
|
+
<item translatable="yes" id="none">None</item>
|
746
|
+
<item translatable="yes" id="crossfade">Fade</item>
|
747
|
+
<item translatable="yes" id="slide-left-right">Slide</item>
|
748
|
+
</items>
|
749
|
+
</object>
|
750
|
+
<packing>
|
751
|
+
<property name="left-attach">1</property>
|
752
|
+
<property name="top-attach">1</property>
|
753
|
+
</packing>
|
754
|
+
</child>
|
755
|
+
</object>
|
756
|
+
</child>
|
757
|
+
</object>
|
758
|
+
</child>
|
759
|
+
</template>
|
760
|
+
</interface>
|
761
|
+
```
|
762
|
+
Next comes the dialog subclass.
|
763
|
+
|
764
|
+
```ruby
|
765
|
+
class ExampleAppPrefs < Gtk::Dialog
|
766
|
+
type_register
|
767
|
+
class << self
|
768
|
+
def init
|
769
|
+
set_template(:resource => "/org/gtk/exampleapp/prefs.ui")
|
770
|
+
bind_template_child("font")
|
771
|
+
bind_template_child("transition")
|
772
|
+
end
|
773
|
+
end
|
774
|
+
def initialize(args)
|
775
|
+
parent = args[:transient_for]
|
776
|
+
bar = args[:use_header_bar]
|
777
|
+
super(:transient_for => parent, :use_header_bar => 1)
|
778
|
+
settings = Gio::Settings.new("org.gtk.exampleapp")
|
779
|
+
settings.bind("font",
|
780
|
+
font,
|
781
|
+
"font",
|
782
|
+
Gio::SettingsBindFlags::DEFAULT)
|
783
|
+
settings.bind("transition",
|
784
|
+
transition,
|
785
|
+
"active-id",
|
786
|
+
Gio::SettingsBindFlags::DEFAULT)
|
787
|
+
end
|
788
|
+
end
|
789
|
+
```
|
790
|
+
|
791
|
+
Nothing new here, it works like previously. The main difference in our application now is that we define what must be done when the *preferences* menu item is clicked.
|
792
|
+
|
793
|
+
```ruby
|
794
|
+
action = Gio::SimpleAction.new("preferences")
|
795
|
+
action.signal_connect("activate") do |_action, _parameter|
|
796
|
+
win = application.windows.first
|
797
|
+
|
798
|
+
prefs = ExampleAppPrefs.new(:transient_for => win,
|
799
|
+
:use_header_bar => true)
|
800
|
+
prefs.present
|
801
|
+
end
|
802
|
+
```
|
803
|
+
Here we just says that when the user activate the *preferences* item, we create an `ExampleAppPrefs` instance and display it. The user can then specify the *font* and *transition* settings for the application. Those settings are used in the `ExampleAppWindow#open` method for example:
|
804
|
+
|
805
|
+
```ruby
|
806
|
+
def open(file)
|
807
|
+
basename = file.basename
|
808
|
+
scrolled = Gtk::ScrolledWindow.new
|
809
|
+
scrolled.show
|
810
|
+
scrolled.set_hexpand(true)
|
811
|
+
scrolled.set_vexpand(true)
|
812
|
+
view = Gtk::TextView.new
|
813
|
+
view.set_editable(false)
|
814
|
+
view.set_cursor_visible(false)
|
815
|
+
view.show
|
816
|
+
scrolled.add(view)
|
817
|
+
stack.add_titled(scrolled, basename, basename)
|
818
|
+
stream = file.read
|
819
|
+
buffer = view.buffer
|
820
|
+
buffer.text = stream.read
|
821
|
+
tag = buffer.create_tag()
|
822
|
+
@settings.bind("font", tag, "font", Gio::SettingsBindFlags::DEFAULT)
|
823
|
+
buffer.apply_tag(tag, buffer.start_iter, buffer.end_iter)
|
824
|
+
end
|
825
|
+
```
|
826
|
+
|
827
|
+
## Adding a search bar
|
828
|
+
https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.10
|
829
|
+
|
830
|
+
* exampleapp7/exampleapp.rb
|
831
|
+
|
832
|
+
We continue to flesh out the functionality of our application. For now, we add search. GTK+ supports this with `Gtk::SearchEntry` and `Gtk::SearchBar`. The search bar is a widget that can slide in from the top to present a search entry.
|
833
|
+
We add a toggle button to the header bar, which can be used to slide out the search bar below the header bar.
|
834
|
+
|
835
|
+
The new window.ui file:
|
836
|
+
|
837
|
+
```xml
|
838
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
839
|
+
<interface>
|
840
|
+
<!-- interface-requires gtk+ 3.8 -->
|
841
|
+
<template class="ExampleAppWindow" parent="GtkApplicationWindow">
|
842
|
+
<property name="title" translatable="yes">Example Application</property>
|
843
|
+
<property name="default-width">600</property>
|
844
|
+
<property name="default-height">400</property>
|
845
|
+
<child>
|
846
|
+
<object class="GtkBox" id="content_box">
|
847
|
+
<property name="visible">True</property>
|
848
|
+
<property name="orientation">vertical</property>
|
849
|
+
<child>
|
850
|
+
<object class="GtkHeaderBar" id="header">
|
851
|
+
<property name="visible">True</property>
|
852
|
+
<child type="title">
|
853
|
+
<object class="GtkStackSwitcher" id="tabs">
|
854
|
+
<property name="visible">True</property>
|
855
|
+
<property name="margin">6</property>
|
856
|
+
<property name="stack">stack</property>
|
857
|
+
</object>
|
858
|
+
</child>
|
859
|
+
<child>
|
860
|
+
<object class="GtkToggleButton" id="search">
|
861
|
+
<property name="visible">True</property>
|
862
|
+
<property name="sensitive">False</property>
|
863
|
+
<style>
|
864
|
+
<class name="image-button"/>
|
865
|
+
</style>
|
866
|
+
<child>
|
867
|
+
<object class="GtkImage" id="search-icon">
|
868
|
+
<property name="visible">True</property>
|
869
|
+
<property name="icon-name">edit-find-symbolic</property>
|
870
|
+
<property name="icon-size">1</property>
|
871
|
+
</object>
|
872
|
+
</child>
|
873
|
+
</object>
|
874
|
+
<packing>
|
875
|
+
<property name="pack-type">end</property>
|
876
|
+
</packing>
|
877
|
+
</child>
|
878
|
+
</object>
|
879
|
+
</child>
|
880
|
+
<child>
|
881
|
+
<object class="GtkSearchBar" id="searchbar">
|
882
|
+
<property name="visible">True</property>
|
883
|
+
<child>
|
884
|
+
<object class="GtkSearchEntry" id="searchentry">
|
885
|
+
<signal name="search-changed" handler="search_text_changed"/>
|
886
|
+
<property name="visible">True</property>
|
887
|
+
</object>
|
888
|
+
</child>
|
889
|
+
</object>
|
890
|
+
</child>
|
891
|
+
<child>
|
892
|
+
<object class="GtkStack" id="stack">
|
893
|
+
<signal name="notify::visible-child" handler="visible_child_changed"/>
|
894
|
+
<property name="visible">True</property>
|
895
|
+
</object>
|
896
|
+
</child>
|
897
|
+
</object>
|
898
|
+
</child>
|
899
|
+
</template>
|
900
|
+
</interface>
|
901
|
+
```
|
902
|
+
Implementing the search needs quite a few code changes that we are not going to completely go over here. The central piece of the search implementation is a signal handler that listens for text changes in the search entry.
|
903
|
+
|
904
|
+
```ruby
|
905
|
+
|
906
|
+
def init
|
907
|
+
set_template(:resource => "/org/gtk/exampleapp/window.ui")
|
908
|
+
bind_template_child("stack")
|
909
|
+
bind_template_child("search")
|
910
|
+
bind_template_child("searchbar")
|
911
|
+
set_connect_func do |name|
|
912
|
+
method(name)
|
913
|
+
end
|
914
|
+
end
|
915
|
+
|
916
|
+
private
|
917
|
+
|
918
|
+
def search_text_changed(search_entry)
|
919
|
+
text = search_entry.text
|
920
|
+
return if text.empty?
|
921
|
+
|
922
|
+
win = search_entry.toplevel
|
923
|
+
tab = win.stack.visible_child
|
924
|
+
view = tab.child
|
925
|
+
buffer = view.buffer
|
926
|
+
range = buffer.start_iter.forward_search(text, Gtk::TextSearchFlags::CASE_INSENSITIVE)
|
927
|
+
return unless range
|
928
|
+
buffer.select_range(range[0], range[1])
|
929
|
+
view.scroll_to_iter(range[0], 0.0, false, 0.0, 0.0)
|
930
|
+
end
|
931
|
+
```
|
932
|
+
|
933
|
+
In this part of code, the use of the method `set_connect_func` will allow us to define private methods as callback that have been set in the handler attributs of the XML ui file. In the code above, we can see that we have defined a private method name `search_text_changed`. In the XML file, there is this line :
|
934
|
+
|
935
|
+
<signal name="search-changed" handler="search_text_changed"/>
|
936
|
+
|
937
|
+
Those pieces together mean that for the signal *search-changed* of the `Gtk::SearchEntry`, trigger the private method of `ExampleAppWindow` that is called `search_text_changed`.
|
938
|
+
|
data/test/run-test.rb
CHANGED
data/test/test-gtk-builder.rb
CHANGED
@@ -19,16 +19,18 @@ class TestGtkBuilder < Test::Unit::TestCase
|
|
19
19
|
assert_kind_of(Gtk::Dialog, builder["dialog1"])
|
20
20
|
end
|
21
21
|
|
22
|
+
test "path" do
|
23
|
+
only_gtk_version(3, 10, 0)
|
24
|
+
builder = Gtk::Builder.new(:path => ui_definition_file.path)
|
25
|
+
assert_kind_of(Gtk::Dialog, builder["dialog1"])
|
26
|
+
end
|
27
|
+
|
22
28
|
test "resource" do
|
23
29
|
only_gtk_version(3, 10, 0)
|
24
|
-
|
25
|
-
Gio::Resources.register(resource)
|
26
|
-
begin
|
30
|
+
register_resource(fixture_path("simple_window.gresource")) do
|
27
31
|
resource_path = "/simple_window/simple_window.ui"
|
28
32
|
builder = Gtk::Builder.new(:resource => resource_path)
|
29
33
|
assert_kind_of(Gtk::Window, builder["window"])
|
30
|
-
ensure
|
31
|
-
Gio::Resources.unregister(resource)
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
@@ -39,43 +41,109 @@ class TestGtkBuilder < Test::Unit::TestCase
|
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
sub_test_case "#add" do
|
45
|
+
sub_test_case ":file" do
|
46
|
+
test "all" do
|
47
|
+
builder = Gtk::Builder.new
|
48
|
+
builder.add(:file => ui_definition_file.path)
|
49
|
+
assert_kind_of(Gtk::Dialog, builder["dialog1"])
|
50
|
+
end
|
51
|
+
|
52
|
+
test ":object_ids" do
|
53
|
+
builder = Gtk::Builder.new
|
54
|
+
builder.add(:file => ui_definition_file.path,
|
55
|
+
:object_ids => ["ok_button"])
|
56
|
+
assert_equal(["ok_button"],
|
57
|
+
builder.objects.collect(&:builder_name).sort)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
sub_test_case ":path" do
|
62
|
+
test "all" do
|
63
|
+
builder = Gtk::Builder.new
|
64
|
+
builder.add(:path => ui_definition_file.path)
|
65
|
+
assert_kind_of(Gtk::Dialog, builder["dialog1"])
|
66
|
+
end
|
67
|
+
|
68
|
+
test ":object_ids" do
|
69
|
+
builder = Gtk::Builder.new
|
70
|
+
builder.add(:path => ui_definition_file.path,
|
71
|
+
:object_ids => ["ok_button"])
|
72
|
+
assert_equal(["ok_button"],
|
73
|
+
builder.objects.collect(&:builder_name).sort)
|
74
|
+
end
|
46
75
|
end
|
47
|
-
assert_kind_of(Gtk::Dialog, builder["dialog1"])
|
48
|
-
end
|
49
76
|
|
50
|
-
|
51
|
-
def test_ascii_only
|
77
|
+
test "path" do
|
52
78
|
builder = Gtk::Builder.new
|
53
|
-
builder.
|
54
|
-
assert_kind_of(Gtk::
|
79
|
+
builder.add(ui_definition_file.path)
|
80
|
+
assert_kind_of(Gtk::ButtonBox, builder["hbuttonbox1"])
|
55
81
|
end
|
56
82
|
|
57
|
-
|
83
|
+
sub_test_case ":resource" do
|
84
|
+
setup do
|
85
|
+
only_gtk_version(3, 12, 0)
|
86
|
+
end
|
87
|
+
|
88
|
+
test "all" do
|
89
|
+
builder = Gtk::Builder.new
|
90
|
+
register_resource(fixture_path("simple_window.gresource")) do
|
91
|
+
resource_path = "/simple_window/simple_window.ui"
|
92
|
+
builder.add(:resource => resource_path)
|
93
|
+
assert_kind_of(Gtk::Window, builder["window"])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
test ":object_ids" do
|
98
|
+
builder = Gtk::Builder.new
|
99
|
+
register_resource(fixture_path("simple_window.gresource")) do
|
100
|
+
resource_path = "/simple_window/simple_window.ui"
|
101
|
+
builder.add(:resource => resource_path,
|
102
|
+
:object_ids => ["label"])
|
103
|
+
assert_equal(["label"],
|
104
|
+
builder.objects.collect(&:builder_name).sort)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
test "resource" do
|
110
|
+
only_gtk_version(3, 12, 0)
|
58
111
|
builder = Gtk::Builder.new
|
59
|
-
|
60
|
-
|
61
|
-
|
112
|
+
register_resource(fixture_path("simple_window.gresource")) do
|
113
|
+
resource_path = "/simple_window/simple_window.ui"
|
114
|
+
builder.add(resource_path)
|
115
|
+
assert_kind_of(Gtk::Window, builder["window"])
|
116
|
+
end
|
62
117
|
end
|
63
|
-
end
|
64
118
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
119
|
+
sub_test_case ":string" do
|
120
|
+
test "ascii only" do
|
121
|
+
builder = Gtk::Builder.new
|
122
|
+
builder.add(:string => ui_definition_simple)
|
123
|
+
assert_kind_of(Gtk::Window, builder["main-window"])
|
124
|
+
end
|
125
|
+
|
126
|
+
test "multibyte characters" do
|
127
|
+
builder = Gtk::Builder.new
|
128
|
+
comment = "<!-- 日本語 -->\n" * 100
|
129
|
+
builder.add(:string => "#{comment}#{ui_definition_simple}")
|
130
|
+
assert_kind_of(Gtk::Window, builder["main-window"])
|
131
|
+
end
|
132
|
+
|
133
|
+
test ":object_ids" do
|
134
|
+
builder = Gtk::Builder.new
|
135
|
+
builder.add(:string => ui_definition,
|
136
|
+
:object_ids => ["ok_button"])
|
137
|
+
assert_equal(["ok_button"],
|
138
|
+
builder.objects.collect(&:builder_name).sort)
|
139
|
+
end
|
69
140
|
end
|
70
|
-
assert_kind_of(Gtk::ButtonBox, builder["hbuttonbox1"])
|
71
|
-
end
|
72
141
|
|
73
|
-
|
74
|
-
|
75
|
-
assert_nothing_raised do
|
142
|
+
test "string" do
|
143
|
+
builder = Gtk::Builder.new
|
76
144
|
builder.add(ui_definition)
|
145
|
+
assert_kind_of(Gtk::Button, builder["ok_button"])
|
77
146
|
end
|
78
|
-
assert_kind_of(Gtk::Button, builder["ok_button"])
|
79
147
|
end
|
80
148
|
|
81
149
|
def test_add_chain
|
@@ -197,4 +265,14 @@ EOX
|
|
197
265
|
xml.close
|
198
266
|
xml
|
199
267
|
end
|
268
|
+
|
269
|
+
def register_resource(path)
|
270
|
+
resource = Gio::Resource.load(path)
|
271
|
+
Gio::Resources.register(resource)
|
272
|
+
begin
|
273
|
+
yield
|
274
|
+
ensure
|
275
|
+
Gio::Resources.unregister(resource)
|
276
|
+
end
|
277
|
+
end
|
200
278
|
end
|