1 /**********************************************************************
2  *
3  *   FreeDoko a Doppelkopf-Game
4  *
5  *   Copyright (C) 2001 – 2018 by Diether Knof and Borg Enders
6  *
7  *   This program is free software; you can redistribute it and/or
8  *   modify it under the terms of the GNU General Public License as
9  *   published by the Free Software Foundation; either version 2 of
10  *   the License, or (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *   You can find this license in the file 'gpl.txt'.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  *   MA  02111-1307  USA
22  *
23  *  Contact:
24  *    Diether Knof dknof@posteo.de
25  *
26  *********************************************************************/
27 
28 #include "constants.h"
29 
30 #ifdef USE_UI_GTKMM
31 
32 #include "cards_order.h"
33 
34 #include "../ui.h"
35 #include "../cards.h"
36 
37 #include <gtkmm/radiobutton.h>
38 #include <gtkmm/grid.h>
39 #include <gtkmm/box.h>
40 #include <gtkmm/arrow.h>
41 #include <gtkmm/image.h>
42 
43 namespace UI_GTKMM_NS {
44 using Direction = ::Preferences::CardsOrder::Direction;
45 
46 /** constructor
47  **/
CardsOrder(Preferences & preferences)48 Preferences::CardsOrder::CardsOrder(Preferences& preferences) :
49   Base(&preferences),
50   preferences_(preferences)
51 {
52   this->init();
53 }
54 
55 /** destructor
56  **/
57 Preferences::CardsOrder::~CardsOrder()
58   = default;
59 
60 /** use the cards order as a widget
61  **/
operator Gtk::Widget&()62 Preferences::CardsOrder::operator Gtk::Widget&()
63 {
64   return *this->container;
65 }
66 
67 /** creates all subelements for the cardsorder
68  **/
69 void
init()70 Preferences::CardsOrder::init()
71 {
72   auto const& cards_order = ::preferences(::Preferences::Type::cards_order);
73   this->container = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL, 1 EX));
74   { // sorted/unsorted
75     auto vbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
76     vbox->set_halign(Gtk::ALIGN_CENTER);
77 
78     Gtk::RadioButton::Group group;
79 
80     this->sorted_button
81       = Gtk::manage(new Gtk::RadioButton(group, _("Button::sorted")));
82     vbox->add(*(this->sorted_button));
83 
84     this->unsorted_button
85       = Gtk::manage(new Gtk::RadioButton(group, _("Button::unsorted")));
86     vbox->add(*(this->unsorted_button));
87 
88     if (cards_order.mixed())
89       this->unsorted_button->set_active();
90     else
91       this->sorted_button->set_active();
92 
93     this->sorted_button->signal_toggled().connect(sigc::mem_fun(*this, &CardsOrder::set_sorted));
94     this->unsorted_button->signal_toggled().connect(sigc::mem_fun(*this, &CardsOrder::set_sorted));
95     this->container->add(*vbox);
96   } // sorted/unsorted
97 
98   { // the cards
99     this->cards_container = Gtk::manage(new Gtk::Grid());
100     auto grid = this->cards_container;
101     this->container->add(*grid);
102     grid->set_row_spacing(1 EX);
103     grid->set_column_spacing(1 EM);
104 
105     for (unsigned p = 0; p < Card::number_of_tcolors; ++p) {
106       { // left/right button
107         auto hbox = Gtk::manage(new Gtk::Box());
108         hbox->set_homogeneous();
109         grid->attach(*hbox, p, 0, 1, 1);
110 
111         auto left_button = Gtk::manage(new Gtk::Button());
112         left_button->add(*Gtk::manage(new Gtk::Arrow(Gtk::ARROW_LEFT,
113                                                      Gtk::SHADOW_OUT)));
114         hbox->add(*left_button);
115         left_button->signal_clicked().connect(sigc::bind<unsigned const>(sigc::mem_fun(*this, &CardsOrder::pos_to_left), p));
116 
117         auto right_button = Gtk::manage(new Gtk::Button());
118         right_button->add(*Gtk::manage(new Gtk::Arrow(Gtk::ARROW_RIGHT,
119                                                       Gtk::SHADOW_OUT)));
120         hbox->add(*right_button);
121         right_button->signal_clicked().connect(sigc::bind<unsigned const>(sigc::mem_fun(*this, &CardsOrder::pos_to_right), p));
122       } // left/right button
123       { // the image
124         if (cards_order.tcolor(p) == Card::trump) {
125           this->sorting_tcolor_image.push_back(this->ui->cards->new_managed_image(Card::club_queen));
126         } else {
127           this->sorting_tcolor_image.push_back(this->ui->cards->new_managed_image(Card(cards_order.tcolor(p), Card::ace)));
128         }
129         grid->attach(*this->sorting_tcolor_image.back(), p, 1, 1, 1);
130       } // the image
131       { // up/down buttons
132         auto vbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
133         grid->attach(*vbox, p, 2, 1, 1);
134 
135         Gtk::RadioButton::Group group;
136         this->sorting_up_button.push_back(Gtk::manage(new Gtk::RadioButton(group, _(Direction::up))));
137         vbox->add(*(this->sorting_up_button.back()));
138 
139         this->sorting_down_button.push_back(Gtk::manage(new Gtk::RadioButton(group, _(Direction::down))));
140         vbox->add(*(this->sorting_down_button.back()));
141 
142         // events
143         this->sorting_up_button.back()->set_active(cards_order.direction(p) == Direction::up);
144         this->sorting_down_button.back()->set_active(cards_order.direction(p) == Direction::down);
145         this->sorting_up_button.back()->signal_toggled().connect(sigc::bind<unsigned const>(sigc::mem_fun(*this, &CardsOrder::set_direction), p));
146         this->sorting_down_button.back()->signal_toggled().connect(sigc::bind<unsigned const>(sigc::mem_fun(*this, &CardsOrder::set_direction), p));
147       } // up/down buttons
148     } // for (c < Card::number_of_tcolors)
149   } // the cards
150 }
151 
152 /** update the cards order
153  **/
154 void
update()155 Preferences::CardsOrder::update()
156 {
157   auto& cards_order = ::preferences(::Preferences::Type::cards_order);
158   if (cards_order.mixed()) {
159     this->unsorted_button->set_active();
160     this->cards_container->set_sensitive(false);
161   } else {
162     this->sorted_button->set_active();
163     this->cards_container->set_sensitive(true);
164 
165     for (unsigned p = 0; p < Card::number_of_tcolors; ++p) {
166       if (cards_order.tcolor(p) == Card::trump)
167         this->ui->cards->change_managed(this->sorting_tcolor_image[p],
168                                         Card::club_queen);
169       else
170         this->ui->cards->change_managed(this->sorting_tcolor_image[p],
171                                         Card(cards_order.tcolor(p), Card::ace));
172 
173       if (cards_order.direction(p)
174           == Direction::up)
175         this->sorting_up_button[p]->set_active();
176       else
177         this->sorting_down_button[p]->set_active();
178 
179     } // for (n < Card::number_of_tcolors)
180   } // if !(::preferences(::Preferences::Type::cards_order).mixed())
181 }
182 
183 /** event: set the sorting direction
184  **
185  ** @param    pos   the position which is changed
186  **/
187 void
set_direction(unsigned const pos)188 Preferences::CardsOrder::set_direction(unsigned const pos)
189 {
190   auto& cards_order = ::preferences(::Preferences::Type::cards_order);
191   cards_order.sorted_set(true);
192   if (this->sorting_up_button[pos]->get_active())
193     cards_order.direction_set(pos, Direction::up);
194   else
195     cards_order.direction_set(pos, Direction::down);
196 }
197 
198 /** event: shift the type at 'pos' one position to the left
199  **
200  ** @param    pos   the position which is shifted
201  **/
202 void
pos_to_left(unsigned const pos)203 Preferences::CardsOrder::pos_to_left(unsigned const pos)
204 {
205   auto& cards_order = ::preferences(::Preferences::Type::cards_order);
206   cards_order.sorted_set(true);
207   cards_order.pos_to_left(pos);
208 }
209 
210 /** event: shift the type at 'pos' one position to the right
211  **
212  ** @param    pos   the position which is shifted
213  **/
214 void
pos_to_right(unsigned const pos)215 Preferences::CardsOrder::pos_to_right(unsigned const pos)
216 {
217   auto& cards_order = ::preferences(::Preferences::Type::cards_order);
218   cards_order.sorted_set(true);
219   cards_order.pos_to_right(pos);
220 }
221 
222 /** event: set the sorted state
223  **/
224 void
set_sorted()225 Preferences::CardsOrder::set_sorted()
226 {
227   auto& cards_order = ::preferences(::Preferences::Type::cards_order);
228   cards_order.sorted_set(this->sorted_button->get_active());
229 }
230 
231 } // namespace UI_GTKMM_NS
232 
233 #endif // #ifdef USE_UI_GTKMM
234