1 /* GTK-based button bar
2  * Copyright (c) 2021 Piotr Miller
3  * e-mail: nwg.piotr@gmail.com
4  * Website: http://nwg.pl
5  * Project: https://github.com/nwg-piotr/nwg-launchers
6  * License: GPL3
7  * *
8  * Credits for window transparency go to AthanasiusOfAlex at https://stackoverflow.com/a/21460337
9  * transparent.cpp
10  * Code adapted from 'alphademo.c' by Mike
11  * (http://plan99.net/~mike/blog--now a dead link--unable to find it.)
12  * as modified by karlphillip for StackExchange:
13  * (https://stackoverflow.com/questions/3908565/how-to-make-gtk-window-background-transparent)
14  * Re-worked for Gtkmm 3.0 by Louis Melahn, L.C. January 31, 2014.
15  * */
16 
17 #include "charconv-compat.h"
18 #include "nwg_tools.h"
19 #include "bar.h"
20 
BarConfig(const InputParser & parser,const Glib::RefPtr<Gdk::Screen> & screen)21 BarConfig::BarConfig(const InputParser& parser, const Glib::RefPtr<Gdk::Screen>& screen):
22     Config{ parser, "~nwgbar", "~nwgbar", screen }
23 {
24     if (parser.cmdOptionExists("-v")) {
25         orientation = Orientation::Vertical;
26     }
27     if (auto tname = parser.getCmdOption("-t"); !tname.empty()) {
28         definition_file = tname;
29     }
30     if (auto i_size = parser.getCmdOption("-s"); !i_size.empty()) {
31         int i_s;
32         if (parse_number(i_size, i_s)) {
33             if (i_s >= 16 && i_s <= 2048) {
34                 icon_size = i_s;
35             } else {
36                 Log::error("Size must be in range 16 - 2048\n");
37             }
38         } else {
39             Log::error("Image size should be valid integer in range 16 - 2048\n");
40         }
41     }
42 }
43 
BarWindow(Config & config)44 BarWindow::BarWindow(Config& config): PlatformWindow(config) {
45     // scrolled_window -> outer_box -> inner_hbox -> grid
46     grid.set_column_spacing(5);
47     grid.set_row_spacing(5);
48     grid.set_column_homogeneous(true);
49     outer_box.set_spacing(15);
50     inner_hbox.set_name("bar");
51     switch (config.halign) {
52         case HAlign::Left:  inner_hbox.pack_start(grid, false, false); break;
53         case HAlign::Right: inner_hbox.pack_end(grid, false, false); break;
54         default: inner_hbox.pack_start(grid, true, false);
55     }
56     switch (config.valign) {
57         case VAlign::Top:    outer_box.pack_start(inner_hbox, false, false); break;
58         case VAlign::Bottom: outer_box.pack_end(inner_hbox, false, false); break;
59         default: outer_box.pack_start(inner_hbox, Gtk::PACK_EXPAND_PADDING);
60     }
61     scrolled_window.add(outer_box);
62     add(scrolled_window);
63     show_all_children();
64 }
65 
on_button_press_event(GdkEventButton * button)66 bool BarWindow::on_button_press_event(GdkEventButton* button) {
67     (void)button;
68     this->close();
69     return true;
70 }
71 
on_key_press_event(GdkEventKey * key_event)72 bool BarWindow::on_key_press_event(GdkEventKey* key_event) {
73     if (key_event -> keyval == GDK_KEY_Escape) {
74         this->close();
75     }
76     //if the event has not been handled, call the base class
77     return CommonWindow::on_key_press_event(key_event);
78 }
79 
80 /*
81  * Constructor is required for std::vector::emplace_back to work
82  * It is not needed when compiling with C++20 and greater
83  * */
BarEntry(std::string name,std::string exec,std::string icon)84 BarEntry::BarEntry(std::string name, std::string exec, std::string icon)
85  : name(std::move(name)), exec(std::move(exec)), icon(std::move(icon)) {}
86 
BarBox(Glib::ustring name,Glib::ustring exec,Glib::ustring comment)87 BarBox::BarBox(Glib::ustring name, Glib::ustring exec, Glib::ustring comment)
88  : AppBox(std::move(name), std::move(exec), std::move(comment)) {}
89 
on_button_press_event(GdkEventButton * event)90 bool BarBox::on_button_press_event(GdkEventButton* event) {
91     (void)event; // suppress warning
92 
93     this->activate();
94     return false;
95 }
96 
on_activate()97 void BarBox::on_activate() {
98     try {
99         Glib::spawn_command_line_async(exec);
100     } catch (const Glib::SpawnError& error) {
101         Log::error("Failed to run command: ", error.what());
102     } catch (const Glib::ShellError& error) {
103         Log::error("Failed to run command: ", error.what());
104     }
105     dynamic_cast<BarWindow*>(this->get_toplevel())->close();
106 }
107