1 //  Copyright (C) 2011, 2014, 2015, 2020 Ben Asselstine
2 //
3 //  This program is free software; you can redistribute it and/or modify
4 //  it under the terms of the GNU General Public License as published by
5 //  the Free Software Foundation; either version 3 of the License, or
6 //  (at your option) any later version.
7 //
8 //  This program is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //  GNU Library General Public License for more details.
12 //
13 //  You should have received a copy of the GNU General Public License
14 //  along with this program; if not, write to the Free Software
15 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 //  02110-1301, USA.
17 
18 #include <config.h>
19 
20 #include <gtkmm.h>
21 
22 #include "stack-army-button.h"
23 #include "stack.h"
24 #include "army.h"
25 
26 #include "input-helpers.h"
27 #include "builder-cache.h"
28 #include "army-info-tip.h"
29 #include "ucompose.hpp"
30 #include "ImageCache.h"
31 #include "File.h"
32 #include "playerlist.h"
33 #include "player.h"
34 #include "shield.h"
35 #include "font-size.h"
36 
create()37 StackArmyButton * StackArmyButton::create()
38 {
39   Glib::ustring file = "stack-army-button-large-screen.ui";
40   Glib::RefPtr<Gtk::Builder> xml = BuilderCache::get(file);
41 
42   StackArmyButton *box;
43   xml->get_widget_derived("box", box);
44   box->d_stack = NULL;
45   box->d_army = NULL;
46   box->d_circle_colour_id = 0;
47   box->army_button->set_active(false);
48   return box;
49 }
50 
StackArmyButton(BaseObjectType * baseObject,const Glib::RefPtr<Gtk::Builder> & xml)51 StackArmyButton::StackArmyButton(BaseObjectType* baseObject, const Glib::RefPtr<Gtk::Builder> &xml)
52   : Gtk::Box(baseObject)
53 {
54   army_info_tip = NULL;
55   xml->get_widget("army_button", army_button);
56   xml->get_widget("army_image", army_image);
57   xml->get_widget("army_label", army_label);
58   xml->get_widget("eventbox", eventbox);
59   eventbox->add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
60   xml->get_widget("stack_button", stack_button);
61   xml->get_widget("stack_image", stack_image);
62   xml->get_widget("stack_button_container", stack_button_container);
63   memset (army_conn, 0, sizeof (army_conn));
64 }
65 
~StackArmyButton()66 StackArmyButton::~StackArmyButton()
67 {
68   if (army_info_tip)
69     delete army_info_tip;
70 }
71 
update_stack_button(bool selected)72 void StackArmyButton::update_stack_button(bool selected)
73 {
74   if (d_stack)
75     {
76       stack_image->clear();
77       if (selected)
78         stack_image->property_pixbuf() =
79           stack_button->render_icon_pixbuf(Gtk::Stock::YES, Gtk::ICON_SIZE_MENU);
80       else
81         stack_image->property_pixbuf() =
82           stack_button->render_icon_pixbuf(Gtk::Stock::NO, Gtk::ICON_SIZE_MENU);
83       stack_button->show();
84     }
85   else
86     stack_button->hide();
87 }
88 
on_army_button_event(GdkEventButton * e)89 bool StackArmyButton::on_army_button_event(GdkEventButton *e)
90 {
91   MouseButtonEvent ev = to_input_event(e);
92   if (ev.button == MouseButtonEvent::RIGHT_BUTTON &&
93       ev.state == MouseButtonEvent::PRESSED)
94     {
95       if (army_info_tip)
96         delete army_info_tip;
97       army_info_tip = new ArmyInfoTip(army_button, d_army);
98       return true;
99     }
100   else if (ev.button == MouseButtonEvent::RIGHT_BUTTON &&
101            ev.state == MouseButtonEvent::RELEASED)
102     {
103       if (army_info_tip)
104         {
105           delete army_info_tip;
106           army_info_tip = NULL;
107         }
108       return true;
109     }
110 
111   return false;
112 }
113 
fill_buttons()114 void StackArmyButton::fill_buttons()
115 {
116   fill_army_button();
117   fill_stack_button();
118 }
119 
fill_army_button()120 void StackArmyButton::fill_army_button()
121 {
122   Player *p = Playerlist::getActiveplayer();
123   ImageCache *gc = ImageCache::getInstance();
124   if (d_army)
125     {
126       bool greyed_out = false;
127       Stack *active_stack = p->getActivestack();
128       if (active_stack->getArmyById(d_army->getId()) == NULL)
129         greyed_out = true;
130       army_image->property_pixbuf() =
131         gc->getCircledArmyPic(p->getArmyset(), d_army->getTypeId(),
132                               p, d_army->getMedalBonuses(), greyed_out,
133                               !greyed_out ? p->getId() : d_circle_colour_id,
134                               true,
135                               FontSize::getInstance ()->get_height ())->to_pixbuf();
136 
137       Pango::AttrList attrs;
138       Pango::Attribute scale = Pango::Attribute::create_attr_scale(1.2);
139       attrs.insert(scale);
140       army_label->set_attributes(attrs);
141       army_label->set_label(String::ucompose("%1", d_army->getMoves()));
142     }
143   else
144     {
145       army_image->property_pixbuf() =
146         gc->getCircledArmyPic(p->getArmyset(), 0, p, NULL, false,
147                               Shield::NEUTRAL, false,
148                               FontSize::getInstance ()->get_height ())->to_pixbuf();
149 
150       stack_image->clear();
151       army_label->set_text("  ");
152     }
153 }
154 
fill_stack_button()155 void StackArmyButton::fill_stack_button()
156 {
157   update_stack_button
158     (d_stack == Playerlist::getActiveplayer()->getActivestack());
159 }
160 
clear_signals()161 void StackArmyButton::clear_signals()
162 {
163   //clear the old signals
164   stack_conn.disconnect();
165   for (unsigned int i = 0; i < 3; i++)
166     army_conn[i].disconnect();
167 }
168 
setup_signals()169 void StackArmyButton::setup_signals()
170 {
171   clear_signals();
172   if (d_stack)
173     stack_conn = stack_button->signal_clicked().connect
174       (sigc::mem_fun(stack_clicked, &sigc::signal<void>::emit));
175   if (d_army)
176     {
177       army_conn[0] = army_button->signal_toggled().connect
178         (sigc::mem_fun(army_toggled, &sigc::signal<void>::emit));
179       army_conn[1] = army_button->signal_button_press_event().connect
180         (sigc::mem_fun(*this, &StackArmyButton::on_army_button_event), false);
181       army_conn[2] = army_button->signal_button_release_event().connect
182         (sigc::mem_fun(*this, &StackArmyButton::on_army_button_event), false);
183     }
184 }
185 
reset()186 void StackArmyButton::reset()
187 {
188   clear_signals();
189   army_button->set_sensitive(true);
190   stack_button->set_sensitive(true);
191   draw(NULL, NULL, 0, false);
192   army_button->set_sensitive(false);
193   stack_button->set_sensitive(false);
194 }
195 
draw(Stack * s,Army * a,guint32 circle_colour_id,bool toggled)196 void StackArmyButton::draw(Stack *s, Army *a, guint32 circle_colour_id, bool toggled)
197 {
198   d_stack = s;
199   d_army = a;
200   d_circle_colour_id = circle_colour_id;
201   army_button->set_sensitive(true);
202   stack_button->set_sensitive(true);
203   if (army_button->get_active() != toggled)
204     army_button->set_active(toggled);
205   fill_buttons();
206   setup_signals();
207 }
208