Merge lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
- economy-target-profiles
- Merge into trunk
Status: | Merged | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 9130 | ||||||||||||||||
Proposed branch: | lp:~widelands-dev/widelands/economy-target-profiles | ||||||||||||||||
Merge into: | lp:widelands | ||||||||||||||||
Diff against target: |
2067 lines (+1248/-203) 20 files modified
data/tribes/economy_profiles/atlanteans (+93/-0) data/tribes/economy_profiles/barbarians (+85/-0) data/tribes/economy_profiles/empire (+93/-0) data/tribes/economy_profiles/frisians (+97/-0) src/logic/filesystem_constants.h (+2/-0) src/logic/map_objects/tribes/tribe_descr.cc (+0/-40) src/logic/map_objects/tribes/tribe_descr.h (+0/-11) src/logic/map_objects/tribes/tribes.cc (+1/-6) src/logic/map_objects/tribes/ware_descr.h (+2/-4) src/logic/playercommand.h (+2/-0) src/notifications/note_ids.h (+1/-0) src/wui/CMakeLists.txt (+2/-0) src/wui/economy_options_window.cc (+512/-55) src/wui/economy_options_window.h (+91/-2) src/wui/inputqueuedisplay.cc (+6/-6) src/wui/inputqueuedisplay.h (+1/-1) src/wui/ware_statistics_menu.cc (+49/-22) src/wui/ware_statistics_menu.h (+14/-0) src/wui/waresdisplay.cc (+154/-54) src/wui/waresdisplay.h (+43/-2) |
||||||||||||||||
To merge this branch: | bzr merge lp:~widelands-dev/widelands/economy-target-profiles | ||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
GunChleoc | Approve | ||
Toni Förster | Approve | ||
kaputtnik (community) | testing | Approve | |
Review via email: mp+366987@code.launchpad.net |
This proposal supersedes a proposal from 2019-05-04.
Commit message
Users can define and save their own profiles of economy target quantities.
Redesigned the economy options menu.
WaresDisplays and will relayout themselves dynamically on fullscreen switch.
Description of the change
For each tribe, I added two profiles: "Efficiency" is equal to the changes proposed previously, and "Stockpile" is for people who, well, like to stockpile stuff. Additionally there is an unchangeable "Default" pseudo-profile that resets items to the default settings.
To apply a profile, select the items you wish to change and choose the profile from the dropdown. Use "Save" to save your current settings as a profile. The save window also allows you to delete profiles.
bunnybot (widelandsofficial) wrote : Posted in a previous version of this proposal | # |
GunChleoc (gunchleoc) wrote : Posted in a previous version of this proposal | # |
2 Comments. Will do some testing.
Benedikt Straub (nordfriese) wrote : Posted in a previous version of this proposal | # |
Addressed the reviews: The panels now set hgaps to fill the entire available space, and the profiles are stored in tribes/
GunChleoc (gunchleoc) wrote : Posted in a previous version of this proposal | # |
New code LGTM.
I am wondering whether we want to save this as Lua tables? I already have the code finished in the spritesheets branch and could pull it out into a separate branch, since spritesheets aren't ready yet.
Benedikt Straub (nordfriese) wrote : Posted in a previous version of this proposal | # |
Is there a reason why you prefer LuaTables over profile? Personally I find Profile much easier to use for configs that the user has no reason to manually edit.
Regarding the suggestion in the bug report – A spinbox would make sense, but what value should it display when several wares with different settings are selected?
GunChleoc (gunchleoc) wrote : Posted in a previous version of this proposal | # |
All the tribe's configuration is in LuaTables, so I guess mainly for consistency - I don't feel strongly about this though.
Good point about the value in the spinbox - I still think we should have the possibility of having steps of 10 though. Maybe fake it with 4 buttons and make them look like the spinbox buttons?
bunnybot (widelandsofficial) wrote : Posted in a previous version of this proposal | # |
Continuous integration builds have changed state:
Travis build 4901. State: failed. Details: https:/
Appveyor build 4682. State: failed. Details: https:/
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4904. State: passed. Details: https:/
Appveyor build 4685. State: failed. Details: https:/
Benedikt Straub (nordfriese) wrote : | # |
Implemented the comments from the bug report
kaputtnik (franku) wrote : | # |
Really nice, thanks :-)
It's good that changing a value will show no text in the editbox, so one can immediately see that there is no profile saved for the chosen value(s).
After playing around with the tabs and switching between wares/workers, i found that loading a profile will only apply to the items in the actual tab (wares/workers). Is this correct?
We may need an entry in the help for this window. But this can be done in a separate branch.
Benedikt Straub (nordfriese) wrote : | # |
Yes, all changes are only ever applied to the active tab. The inactive tab will never change.
A helpful explanation should be added to the economy tutorial IMHO.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4911. State: passed. Details: https:/
Appveyor build 4692. State: success. Details: https:/
Toni Förster (stonerl) wrote : | # |
One major problem. Pressing the save button pauses the game without actually showing, that the game is paused. That might tolerable in single player, but in multiplayer it pauses the game for all participants. This should not happen.
Also get this warning during compiling:
src/wui/
Toni Förster (stonerl) wrote : | # |
Figured it is worse. The game stalls, it is not paused. The game stalls as long as the save window is open, when closing the windows it fast forwards the time. e.g. Opening the window at 1.30 and leaving it open for 1 minute, means after closing it, the time will fast-forward to 2.30.
Benedikt Straub (nordfriese) wrote : | # |
I made the save dialog modal, my mistake. This was supposed to ensure that only one save window is open at the time and the parent window won´t disappear while it´s open.
Now I ensure this another way; the game progresses normally and input isn´t blocked.
The last revision now has a strange behaviour though that the save window doesn´t close by itself if you destroy the last flag of the economy, which I don´t understand yet…
GunChleoc (gunchleoc) wrote : | # |
If you want to ensure that there is onyl 1 save dialog, you can make it a UniqueWindow.
The economy options should control the lifetime of the save window. This is a bit tricky when you merge 2 economies.
Benedikt Straub (nordfriese) wrote : | # |
Thanks for the suggestion, I´ll use UniqueWindow then :)
Currently, I am closing the save dialog from the EconomyOptionsW
GunChleoc (gunchleoc) wrote : | # |
Have a look at EconomyOptionsW
Benedikt Straub (nordfriese) wrote : | # |
I decided against UniqueWindow after all, it seems a bit overkill. All the remaining problems should be fixed now.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4930. State: passed. Details: https:/
Appveyor build 4711. State: failed. Details: https:/
Toni Förster (stonerl) wrote : | # |
Very good so far, two nits though.
Stockpile and Efficiency Profiles should be changeable but not deletable. Also, when deleting the active profile it should switch back to default. Otherwise, the deleted one is still shown as active and the drop-down list has an empty entry.
Toni Förster (stonerl) wrote : | # |
BTW while we're on it. Should we consider presetting all Profiles with sane values?
Benedikt Straub (nordfriese) wrote : | # |
> Stockpile and Efficiency Profiles should be changeable but not deletable
Okay, I´ll add a "undeletable" tag to these profiles
> when deleting the active profile it should switch back to default. Otherwise, the deleted one is still shown as active
I thought we had agreed to not show "Default" if the settings are not equal to the default values? Sounds like the bug is that deleted profiles need to be removed from the dropdown and the dropdown set to "" then.
> Should we consider presetting all Profiles with sane values?
I preset "Stockpile" with my own personal preferences, and "Efficiency" is a copy of the old proposal. There is room for discussion of better presets…
Benedikt Straub (nordfriese) wrote : | # |
The predefined profiles are now undeletable.
But I can´t reproduce this:
> Otherwise, the deleted one is still shown as active and the drop-down list has an empty entry.
It works fine for me: When deleting the active profile, the dropdown immediately switches to "".
Toni Förster (stonerl) wrote : | # |
Have a look at the picture. I deleted the profile test.
Benedikt Straub (nordfriese) wrote : | # |
I still can´t reproduce, it works fine for me:
https:/
(screenshot taken directly after I deleted the profile "Zero")
Toni Förster (stonerl) wrote : | # |
Maybe I just failed to explain it. Have a look at the video.
Benedikt Straub (nordfriese) wrote : | # |
Either I´m blind or I don´t see what I am doing wrong…
https:/
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4940. State: passed. Details: https:/
Appveyor build 4721. State: success. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
In your video, I don't see you accessing the dropdown in the economy window after the deletion.
Benedikt Straub (nordfriese) wrote : | # |
Updated video: https:/
I still get a different result by the same steps and have no idea why :(
Toni Förster (stonerl) : | # |
Benedikt Straub (nordfriese) wrote : | # |
Hmm... it seems like the dropdown´s entries and selection are not updated correctly for some reason which is beyond my understanding. The "Not Selected" message is only the consequence of an upstream failure which I suspect in update_profiles(). I have rewritten it, can you try if the problem still exists?
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4972. State: failed. Details: https:/
Appveyor build 4753. State: success. Details: https:/
Toni Förster (stonerl) wrote : | # |
Still shows "Not Selected" instead of an empty entry.
Benedikt Straub (nordfriese) wrote : | # |
I am at a loss. I have now pushed a revision that adds lots of logging output.
When I perform these steps:
– Open the options window from a flag
– Change some values
– Click the save button
– Save the profile as "test"
– (now the dropdown shows "test")
– close the options window
– re-open it (the dropdown shows "test")
– Click the save button
– select profile "test"
– click delete
– (the dropdown now shows "")
– close the save dialog
– open the dropdown (still showing "")
– close the options window
– re-open it (the dropdown shows "")
I attached the log output I received to the bug. Please post the log output you receive so we can compare…
https:/
Toni Förster (stonerl) wrote : | # |
crash:
NOCOM: EconomyOptionsW
Planning to select »Default«
Did not select it because it is already selected
NOCOM: EconomyOptionsW
Desired and actual state of the empty »« profile don´t match
NOCOM: EconomyOptionsW
Added Default
Added Efficiency
Added Stockpile
Added the empty profile
NOCOM: EconomyOptionsW
Planning to select »Project-
Report-
POT-Creation-Date: 2019-04-22 05:17+0000
PO-Revision-Date: 2019-03-03 08:20+0000
Last-Translator: GunChleoc
Language-Team: English (United States) (http://
Language: en_US
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-
Plural-Forms: nplurals=2; plural=(n != 1);
«
Selected it!
Assertion failed: (dropdown_
Abort trap: 6
Benedikt Straub (nordfriese) wrote : | # |
Ah yes, it seems like the translation for the empty string is not as accurate as I expected it...
The dropdown contains translated entries, so I tell it to select the translated name of the applicable profile. I don´t know what the cause of this weird translation is, perhaps your i18n library dislikes _("") expressions? Please retry with the last revision…
Toni Förster (stonerl) wrote : | # |
r9110 fixed it. Thanks allot.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 5002. State: passed. Details: https:/
Appveyor build 4783. State: success. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
Yep, translating the empty string is a bad idea.
Dropdowns, table and listselect entries have 2 data elements - one is the actual data (Entry value), the other one is a translatable label (const std::string& name). You need to compare the actual data, not the translatable label.
void add(const std::string& name,
Entry value,
const Image* pic = nullptr,
const bool select_this = false,
const std::string& tooltip_text = std::string()) {
entry_
BaseDropdown:
}
Toni Förster (stonerl) wrote : | # |
I think I forgot to approve this :)
GunChleoc (gunchleoc) wrote : | # |
This will break once translations come in.
GunChleoc (gunchleoc) wrote : | # |
I have just tested the relayouting when fullscreen switching. It works well for warehouses and the stock statistics.
In the ware statistics, the bottom slider and text are cut off.
In the economy window, we get wide gaps between the columns and some extra space on the left and right of the button rows.
GunChleoc (gunchleoc) wrote : | # |
Also:
=======
==6158==ERROR: AddressSanitizer: heap-use-after-free on address 0x61800003eda0 at pc 0x55fbbb8f1299 bp 0x7ffc346f2020 sp 0x7ffc346f2010
READ of size 8 at 0x61800003eda0 thread T0
#0 0x55fbbb8f1298 in std::_Deque_
#1 0x55fbbb8f1232 in std::deque<
#2 0x55fbbb8ea1a3 in UI::BaseListsel
#3 0x55fbbb8cf6fc in UI::BaseDropdow
#4 0x55fbbb52cb26 in UI::Dropdown<
#5 0x55fbbc30e0ec in EconomyOptionsW
#6 0x55fbbc30e17f in EconomyOptionsW
#7 0x55fbbb910d1d in UI::Panel:
#8 0x55fbbb9108ce in UI::Panel::~Panel() ../src/
#9 0x55fbbba82826 in InteractiveBase
#10 0x55fbbbae54c1 in InteractiveGame
#11 0x55fbbbaea715 in InteractivePlay
#12 0x55fbbbaea73d in InteractivePlay
#13 0x55fbbb6a9884 in std::default_
#14 0x55fbbb6a817e in std::unique_
#15 0x55fbbb69d8f8 in Widelands:
#16 0x55fbbb6b7242 in Widelands:
#17 0x55fbbb39b1a0 in WLApplication:
#18 0x55fbbb399280 in WLApplication:
#19 0x55fbbb3983cb in WLApplication:
#20 0x55fbbb38f3b1 in WLApplication:
#21 0x55fbbb38b14e in main ../src/main.cc:44
#22 0x7f3374bb0b96 in __libc_start_main (/lib/x86_
#23 0x55fbbb38afc9 in _start (economy-
Benedikt Straub (nordfriese) wrote : | # |
Implemented or replied to the diff comments.
The ASan error is in trunk and can happen everywhere there are dropdowns. For example, when I´m thrown back to the main menu by an error from a fsmenu screen that has one I already got this crash. It can appear whenever destroying a window that contains a dropdown on a lower level. Happens very rarely though, so I did not report it…
> In the ware statistics, the bottom slider and text are cut off.
> In the economy window, we get wide gaps between the columns and some extra space on the left and right of the button rows.
They probably do not layout properly yet… will look into it
Benedikt Straub (nordfriese) wrote : | # |
Layouting fixed. Ware statistics now sets a hgap as well
GunChleoc (gunchleoc) wrote : | # |
You can now get rid of the second_phase variable entirely. Just check for !anything_selected at the end of the loop, then you can also get rid of
if (anything_selected) {
return;
}
Confirmed that the layouting is fixed. The ware statistics doesn't fit yet at 800x600 resolution, can you give it 1 less row for that?
Also added 1 comment.
Benedikt Straub (nordfriese) wrote : | # |
Ware stats menu fixed. It is already too large in trunk, but I made it shorter now.
We still need knowledge of the phase we´re in during the loop so we can know whether to change the target for all wares or only for the selected. Since anything_selected may change during the loop, we need two variables here.
The Dropdown implementation specifies:
template <typename Entry> class Dropdown : public BaseDropdown {
void add(const std::string& name,
Entry value, …);
void select(const Entry& entry);
const Entry& get_selected() const;
…
}
(With Entry = std::string here.) Since Entry is the descname (right?), this looks as if the selection is handled by descname rather than internal name…
GunChleoc (gunchleoc) wrote : | # |
> Since Entry is the descname (right?),
Wrong. The dropdown also comes with documentation:
/// Add an element to the list
/// \param name the display name of the entry
/// \param value the index of the entry
/// \param pic an image to illustrate the entry. Can be nullptr for textual dropdowns.
/// \param select_this whether this element should be selected
/// \param tooltip_text a tooltip for this entry
///
/// Text conventions: Title Case for the 'name', Sentence case for the 'tooltip_text'
void add(const std::string& name,
uint32_t value,
const Image* pic = nullptr,
const bool select_this = false,
const std::string& tooltip_text = std::string());
So, the translatable element is:
/// \param name the display name of the entry
GunChleoc (gunchleoc) wrote : | # |
That was the BaseDropdown. The Dropdown template looks like this:
template <typename Entry> class Dropdown : public BaseDropdown {
...
/// Add an element to the list
/// \param name the display name of the entry
/// \param value the value for the entry
/// \param pic an image to illustrate the entry. Can be nullptr in textual dropdowns
/// only.
/// \param select_this whether this element should be selected
/// \param tooltip_text a tooltip for this entry
void add(const std::string& name,
Entry value,
const Image* pic = nullptr,
const bool select_this = false,
const std::string& tooltip_text = std::string()) {
"Entry value" can be any data type you like, "const std::string& name" is the translatable name.
Benedikt Straub (nordfriese) wrote : | # |
Okay, my mistake :)
Double-checked my dropdown usage, should all be fine then…
GunChleoc (gunchleoc) wrote : | # |
I have merged trunk and pushed some changes. Feel free to merge this branch if you agree with them :)
Benedikt Straub (nordfriese) wrote : | # |
Thanks everyone for the reviews, and thanks for the fixes :)
@bunnybot merge
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 5080. State: errored. Details: https:/
Appveyor build 4860. State: failed. Details: https:/
bunnybot (widelandsofficial) wrote : | # |
Refusing to merge, since Travis is not green. Use @bunnybot merge force for merging anyways.
Travis build 5080. State: errored. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
Inputqueues again
@bunnybot merge force
Preview Diff
1 | === added file 'data/images/ui_basic/scrollbar_down_fast.png' | |||
2 | 0 | Binary files data/images/ui_basic/scrollbar_down_fast.png 1970-01-01 00:00:00 +0000 and data/images/ui_basic/scrollbar_down_fast.png 2019-05-29 06:43:44 +0000 differ | 0 | Binary files data/images/ui_basic/scrollbar_down_fast.png 1970-01-01 00:00:00 +0000 and data/images/ui_basic/scrollbar_down_fast.png 2019-05-29 06:43:44 +0000 differ |
3 | === added file 'data/images/ui_basic/scrollbar_up_fast.png' | |||
4 | 1 | Binary files data/images/ui_basic/scrollbar_up_fast.png 1970-01-01 00:00:00 +0000 and data/images/ui_basic/scrollbar_up_fast.png 2019-05-29 06:43:44 +0000 differ | 1 | Binary files data/images/ui_basic/scrollbar_up_fast.png 1970-01-01 00:00:00 +0000 and data/images/ui_basic/scrollbar_up_fast.png 2019-05-29 06:43:44 +0000 differ |
5 | === added directory 'data/tribes/economy_profiles' | |||
6 | === added file 'data/tribes/economy_profiles/atlanteans' | |||
7 | --- data/tribes/economy_profiles/atlanteans 1970-01-01 00:00:00 +0000 | |||
8 | +++ data/tribes/economy_profiles/atlanteans 2019-05-29 06:43:44 +0000 | |||
9 | @@ -0,0 +1,93 @@ | |||
10 | 1 | # Automatically created by Widelands bzr9094[economy-target-profiles] (Debug) | ||
11 | 2 | |||
12 | 3 | [Default] | ||
13 | 4 | 0=_"Efficiency" | ||
14 | 5 | 1=_"Stockpile" | ||
15 | 6 | |||
16 | 7 | [undeletable] | ||
17 | 8 | 0="true" | ||
18 | 9 | 1="true" | ||
19 | 10 | |||
20 | 11 | [0] | ||
21 | 12 | blackroot_flour="1" | ||
22 | 13 | atlanteans_bread="20" | ||
23 | 14 | bread_paddle="0" | ||
24 | 15 | buckets="0" | ||
25 | 16 | coal="5" | ||
26 | 17 | cornmeal="3" | ||
27 | 18 | diamond="3" | ||
28 | 19 | fire_tongs="1" | ||
29 | 20 | fishing_net="2" | ||
30 | 21 | gold="1" | ||
31 | 22 | gold_ore="1" | ||
32 | 23 | gold_thread="0" | ||
33 | 24 | granite="10" | ||
34 | 25 | hammer="0" | ||
35 | 26 | hook_pole="0" | ||
36 | 27 | hunting_bow="1" | ||
37 | 28 | iron="5" | ||
38 | 29 | iron_ore="1" | ||
39 | 30 | milking_tongs="0" | ||
40 | 31 | pick="1" | ||
41 | 32 | planks="1" | ||
42 | 33 | quartz="3" | ||
43 | 34 | saw="0" | ||
44 | 35 | scythe="0" | ||
45 | 36 | shield_advanced="0" | ||
46 | 37 | shield_steel="0" | ||
47 | 38 | shovel="0" | ||
48 | 39 | smoked_fish="5" | ||
49 | 40 | smoked_meat="3" | ||
50 | 41 | spidercloth="5" | ||
51 | 42 | spider_silk="5" | ||
52 | 43 | tabard="1" | ||
53 | 44 | tabard_golden="0" | ||
54 | 45 | trident_double="0" | ||
55 | 46 | trident_heavy_double="0" | ||
56 | 47 | trident_light="1" | ||
57 | 48 | trident_long="0" | ||
58 | 49 | trident_steel="0" | ||
59 | 50 | atlanteans_horse="1" | ||
60 | 51 | atlanteans_soldier="10" | ||
61 | 52 | |||
62 | 53 | [1] | ||
63 | 54 | blackroot_flour="20" | ||
64 | 55 | atlanteans_bread="30" | ||
65 | 56 | bread_paddle="1" | ||
66 | 57 | buckets="2" | ||
67 | 58 | coal="25" | ||
68 | 59 | cornmeal="20" | ||
69 | 60 | diamond="10" | ||
70 | 61 | fire_tongs="1" | ||
71 | 62 | fishing_net="2" | ||
72 | 63 | gold="20" | ||
73 | 64 | gold_ore="15" | ||
74 | 65 | gold_thread="5" | ||
75 | 66 | granite="30" | ||
76 | 67 | hammer="2" | ||
77 | 68 | hook_pole="1" | ||
78 | 69 | hunting_bow="1" | ||
79 | 70 | iron="25" | ||
80 | 71 | iron_ore="20" | ||
81 | 72 | milking_tongs="1" | ||
82 | 73 | pick="3" | ||
83 | 74 | planks="40" | ||
84 | 75 | quartz="10" | ||
85 | 76 | saw="2" | ||
86 | 77 | scythe="1" | ||
87 | 78 | shield_advanced="1" | ||
88 | 79 | shield_steel="1" | ||
89 | 80 | shovel="2" | ||
90 | 81 | smoked_fish="40" | ||
91 | 82 | smoked_meat="25" | ||
92 | 83 | spidercloth="20" | ||
93 | 84 | spider_silk="15" | ||
94 | 85 | tabard="30" | ||
95 | 86 | tabard_golden="1" | ||
96 | 87 | trident_double="1" | ||
97 | 88 | trident_heavy_double="1" | ||
98 | 89 | trident_light="30" | ||
99 | 90 | trident_long="1" | ||
100 | 91 | trident_steel="1" | ||
101 | 92 | atlanteans_horse="20" | ||
102 | 93 | atlanteans_soldier="20" | ||
103 | 0 | 94 | ||
104 | === added file 'data/tribes/economy_profiles/barbarians' | |||
105 | --- data/tribes/economy_profiles/barbarians 1970-01-01 00:00:00 +0000 | |||
106 | +++ data/tribes/economy_profiles/barbarians 2019-05-29 06:43:44 +0000 | |||
107 | @@ -0,0 +1,85 @@ | |||
108 | 1 | # Automatically created by Widelands bzr9094[economy-target-profiles] (Debug) | ||
109 | 2 | |||
110 | 3 | [Default] | ||
111 | 4 | 0=_"Efficiency" | ||
112 | 5 | 1=_"Stockpile" | ||
113 | 6 | |||
114 | 7 | [undeletable] | ||
115 | 8 | 0="true" | ||
116 | 9 | 1="true" | ||
117 | 10 | |||
118 | 11 | [0] | ||
119 | 12 | ax="1" | ||
120 | 13 | ax_battle="0" | ||
121 | 14 | ax_broad="0" | ||
122 | 15 | ax_bronze="0" | ||
123 | 16 | ax_sharp="0" | ||
124 | 17 | ax_warriors="0" | ||
125 | 18 | beer="0" | ||
126 | 19 | beer_strong="1" | ||
127 | 20 | blackwood="40" | ||
128 | 21 | barbarians_bread="5" | ||
129 | 22 | bread_paddle="0" | ||
130 | 23 | cloth="10" | ||
131 | 24 | coal="20" | ||
132 | 25 | felling_ax="0" | ||
133 | 26 | fire_tongs="1" | ||
134 | 27 | fishing_rod="0" | ||
135 | 28 | gold="1" | ||
136 | 29 | gold_ore="1" | ||
137 | 30 | granite="10" | ||
138 | 31 | grout="1" | ||
139 | 32 | hammer="1" | ||
140 | 33 | helmet="0" | ||
141 | 34 | helmet_mask="0" | ||
142 | 35 | helmet_warhelm="0" | ||
143 | 36 | hunting_spear="0" | ||
144 | 37 | iron="5" | ||
145 | 38 | iron_ore="5" | ||
146 | 39 | kitchen_tools="0" | ||
147 | 40 | meal="5" | ||
148 | 41 | pick="1" | ||
149 | 42 | ration="20" | ||
150 | 43 | scythe="0" | ||
151 | 44 | shovel="0" | ||
152 | 45 | snack="0" | ||
153 | 46 | barbarians_ox="1" | ||
154 | 47 | barbarians_soldier="10" | ||
155 | 48 | |||
156 | 49 | [1] | ||
157 | 50 | ax="30" | ||
158 | 51 | ax_battle="1" | ||
159 | 52 | ax_broad="1" | ||
160 | 53 | ax_bronze="1" | ||
161 | 54 | ax_sharp="1" | ||
162 | 55 | ax_warriors="1" | ||
163 | 56 | beer="15" | ||
164 | 57 | beer_strong="20" | ||
165 | 58 | blackwood="45" | ||
166 | 59 | barbarians_bread="25" | ||
167 | 60 | bread_paddle="1" | ||
168 | 61 | cloth="10" | ||
169 | 62 | coal="25" | ||
170 | 63 | felling_ax="5" | ||
171 | 64 | fire_tongs="1" | ||
172 | 65 | fishing_rod="1" | ||
173 | 66 | gold="20" | ||
174 | 67 | gold_ore="15" | ||
175 | 68 | granite="30" | ||
176 | 69 | grout="20" | ||
177 | 70 | hammer="2" | ||
178 | 71 | helmet="1" | ||
179 | 72 | helmet_mask="1" | ||
180 | 73 | helmet_warhelm="1" | ||
181 | 74 | hunting_spear="1" | ||
182 | 75 | iron="25" | ||
183 | 76 | iron_ore="20" | ||
184 | 77 | kitchen_tools="1" | ||
185 | 78 | meal="15" | ||
186 | 79 | pick="2" | ||
187 | 80 | ration="30" | ||
188 | 81 | scythe="1" | ||
189 | 82 | shovel="1" | ||
190 | 83 | snack="20" | ||
191 | 84 | barbarians_ox="20" | ||
192 | 85 | barbarians_soldier="20" | ||
193 | 0 | 86 | ||
194 | === added file 'data/tribes/economy_profiles/empire' | |||
195 | --- data/tribes/economy_profiles/empire 1970-01-01 00:00:00 +0000 | |||
196 | +++ data/tribes/economy_profiles/empire 2019-05-29 06:43:44 +0000 | |||
197 | @@ -0,0 +1,93 @@ | |||
198 | 1 | # Automatically created by Widelands bzr9094[economy-target-profiles] (Debug) | ||
199 | 2 | |||
200 | 3 | [Default] | ||
201 | 4 | 0=_"Efficiency" | ||
202 | 5 | 1=_"Stockpile" | ||
203 | 6 | |||
204 | 7 | [undeletable] | ||
205 | 8 | 0="true" | ||
206 | 9 | 1="true" | ||
207 | 10 | |||
208 | 11 | [0] | ||
209 | 12 | armor="1" | ||
210 | 13 | armor_chain="1" | ||
211 | 14 | armor_gilded="1" | ||
212 | 15 | armor_helmet="30" | ||
213 | 16 | basket="1" | ||
214 | 17 | beer="1" | ||
215 | 18 | empire_bread="20" | ||
216 | 19 | bread_paddle="0" | ||
217 | 20 | cloth="15" | ||
218 | 21 | coal="5" | ||
219 | 22 | felling_ax="0" | ||
220 | 23 | fire_tongs="1" | ||
221 | 24 | fishing_rod="0" | ||
222 | 25 | flour="20" | ||
223 | 26 | gold="1" | ||
224 | 27 | gold_ore="1" | ||
225 | 28 | granite="10" | ||
226 | 29 | hammer="0" | ||
227 | 30 | hunting_spear="0" | ||
228 | 31 | iron="5" | ||
229 | 32 | iron_ore="3" | ||
230 | 33 | kitchen_tools="0" | ||
231 | 34 | marble="30" | ||
232 | 35 | marble_column="10" | ||
233 | 36 | meal="5" | ||
234 | 37 | meat="20" | ||
235 | 38 | pick="1" | ||
236 | 39 | planks="1" | ||
237 | 40 | ration="20" | ||
238 | 41 | saw="0" | ||
239 | 42 | scythe="0" | ||
240 | 43 | shovel="0" | ||
241 | 44 | spear="1" | ||
242 | 45 | spear_advanced="1" | ||
243 | 46 | spear_heavy="1" | ||
244 | 47 | spear_war="1" | ||
245 | 48 | spear_wooden="30" | ||
246 | 49 | wool="10" | ||
247 | 50 | empire_donkey="1" | ||
248 | 51 | empire_soldier="10" | ||
249 | 52 | |||
250 | 53 | [1] | ||
251 | 54 | armor="1" | ||
252 | 55 | armor_chain="1" | ||
253 | 56 | armor_gilded="1" | ||
254 | 57 | armor_helmet="30" | ||
255 | 58 | basket="1" | ||
256 | 59 | beer="20" | ||
257 | 60 | empire_bread="30" | ||
258 | 61 | bread_paddle="1" | ||
259 | 62 | cloth="15" | ||
260 | 63 | coal="25" | ||
261 | 64 | felling_ax="3" | ||
262 | 65 | fire_tongs="1" | ||
263 | 66 | fishing_rod="1" | ||
264 | 67 | flour="25" | ||
265 | 68 | gold="20" | ||
266 | 69 | gold_ore="15" | ||
267 | 70 | granite="30" | ||
268 | 71 | hammer="2" | ||
269 | 72 | hunting_spear="1" | ||
270 | 73 | iron="25" | ||
271 | 74 | iron_ore="20" | ||
272 | 75 | kitchen_tools="1" | ||
273 | 76 | marble="35" | ||
274 | 77 | marble_column="15" | ||
275 | 78 | meal="20" | ||
276 | 79 | meat="30" | ||
277 | 80 | pick="2" | ||
278 | 81 | planks="40" | ||
279 | 82 | ration="25" | ||
280 | 83 | saw="1" | ||
281 | 84 | scythe="1" | ||
282 | 85 | shovel="1" | ||
283 | 86 | spear="1" | ||
284 | 87 | spear_advanced="1" | ||
285 | 88 | spear_heavy="1" | ||
286 | 89 | spear_war="1" | ||
287 | 90 | spear_wooden="30" | ||
288 | 91 | wool="15" | ||
289 | 92 | empire_donkey="20" | ||
290 | 93 | empire_soldier="20" | ||
291 | 0 | 94 | ||
292 | === added file 'data/tribes/economy_profiles/frisians' | |||
293 | --- data/tribes/economy_profiles/frisians 1970-01-01 00:00:00 +0000 | |||
294 | +++ data/tribes/economy_profiles/frisians 2019-05-29 06:43:44 +0000 | |||
295 | @@ -0,0 +1,97 @@ | |||
296 | 1 | # Automatically created by Widelands bzr9093[economy-target-profiles] (Debug) | ||
297 | 2 | |||
298 | 3 | [Default] | ||
299 | 4 | 0=_"Efficiency" | ||
300 | 5 | 1=_"Stockpile" | ||
301 | 6 | |||
302 | 7 | [undeletable] | ||
303 | 8 | 0="true" | ||
304 | 9 | 1="true" | ||
305 | 10 | |||
306 | 11 | [0] | ||
307 | 12 | clay="30" | ||
308 | 13 | brick="40" | ||
309 | 14 | bread_frisians="20" | ||
310 | 15 | honey_bread="20" | ||
311 | 16 | mead="15" | ||
312 | 17 | fur="10" | ||
313 | 18 | fur_garment="30" | ||
314 | 19 | fur_garment_studded="2" | ||
315 | 20 | fur_garment_golden="2" | ||
316 | 21 | helmet_golden="2" | ||
317 | 22 | sword_short="30" | ||
318 | 23 | sword_long="2" | ||
319 | 24 | sword_broad="2" | ||
320 | 25 | sword_double="2" | ||
321 | 26 | needles="1" | ||
322 | 27 | basket="1" | ||
323 | 28 | beer="1" | ||
324 | 29 | bread_paddle="1" | ||
325 | 30 | cloth="10" | ||
326 | 31 | coal="20" | ||
327 | 32 | felling_ax="0" | ||
328 | 33 | fire_tongs="1" | ||
329 | 34 | fish="20" | ||
330 | 35 | fishing_net="2" | ||
331 | 36 | gold="1" | ||
332 | 37 | gold_ore="1" | ||
333 | 38 | granite="10" | ||
334 | 39 | hammer="1" | ||
335 | 40 | helmet="0" | ||
336 | 41 | hunting_spear="0" | ||
337 | 42 | iron="5" | ||
338 | 43 | iron_ore="3" | ||
339 | 44 | kitchen_tools="0" | ||
340 | 45 | meal="1" | ||
341 | 46 | pick="1" | ||
342 | 47 | ration="20" | ||
343 | 48 | scythe="0" | ||
344 | 49 | shovel="0" | ||
345 | 50 | smoked_fish="20" | ||
346 | 51 | smoked_meat="10" | ||
347 | 52 | frisians_reindeer="1" | ||
348 | 53 | frisians_soldier="10" | ||
349 | 54 | |||
350 | 55 | [1] | ||
351 | 56 | clay="35" | ||
352 | 57 | brick="50" | ||
353 | 58 | bread_frisians="30" | ||
354 | 59 | honey_bread="30" | ||
355 | 60 | mead="30" | ||
356 | 61 | fur="20" | ||
357 | 62 | fur_garment="30" | ||
358 | 63 | fur_garment_studded="2" | ||
359 | 64 | fur_garment_golden="2" | ||
360 | 65 | helmet_golden="2" | ||
361 | 66 | sword_short="30" | ||
362 | 67 | sword_long="2" | ||
363 | 68 | sword_broad="2" | ||
364 | 69 | sword_double="2" | ||
365 | 70 | needles="1" | ||
366 | 71 | basket="1" | ||
367 | 72 | beer="30" | ||
368 | 73 | bread_paddle="1" | ||
369 | 74 | cloth="10" | ||
370 | 75 | coal="35" | ||
371 | 76 | felling_ax="3" | ||
372 | 77 | fire_tongs="2" | ||
373 | 78 | fish="40" | ||
374 | 79 | fishing_net="2" | ||
375 | 80 | gold="20" | ||
376 | 81 | gold_ore="15" | ||
377 | 82 | granite="35" | ||
378 | 83 | hammer="3" | ||
379 | 84 | helmet="2" | ||
380 | 85 | hunting_spear="1" | ||
381 | 86 | iron="25" | ||
382 | 87 | iron_ore="20" | ||
383 | 88 | kitchen_tools="2" | ||
384 | 89 | meal="10" | ||
385 | 90 | pick="3" | ||
386 | 91 | ration="30" | ||
387 | 92 | scythe="2" | ||
388 | 93 | shovel="5" | ||
389 | 94 | smoked_fish="30" | ||
390 | 95 | smoked_meat="20" | ||
391 | 96 | frisians_reindeer="20" | ||
392 | 97 | frisians_soldier="20" | ||
393 | 0 | 98 | ||
394 | === modified file 'src/logic/filesystem_constants.h' | |||
395 | --- src/logic/filesystem_constants.h 2019-04-18 16:50:35 +0000 | |||
396 | +++ src/logic/filesystem_constants.h 2019-05-29 06:43:44 +0000 | |||
397 | @@ -78,4 +78,6 @@ | |||
398 | 78 | /// Filesystem names for config | 78 | /// Filesystem names for config |
399 | 79 | const std::string kConfigFile = "config"; | 79 | const std::string kConfigFile = "config"; |
400 | 80 | 80 | ||
401 | 81 | const std::string kEconomyProfilesDir = "tribes/economy_profiles"; | ||
402 | 82 | |||
403 | 81 | #endif // end of include guard: WL_LOGIC_FILESYSTEM_CONSTANTS_H | 83 | #endif // end of include guard: WL_LOGIC_FILESYSTEM_CONSTANTS_H |
404 | 82 | 84 | ||
405 | === modified file 'src/logic/map_objects/tribes/tribe_descr.cc' | |||
406 | --- src/logic/map_objects/tribes/tribe_descr.cc 2019-05-27 21:04:13 +0000 | |||
407 | +++ src/logic/map_objects/tribes/tribe_descr.cc 2019-05-29 06:43:44 +0000 | |||
408 | @@ -95,8 +95,6 @@ | |||
409 | 95 | load_roads("busy", &busy_road_paths_); | 95 | load_roads("busy", &busy_road_paths_); |
410 | 96 | 96 | ||
411 | 97 | items_table = table.get_table("wares_order"); | 97 | items_table = table.get_table("wares_order"); |
412 | 98 | wares_order_coords_.resize(tribes_.nrwares()); | ||
413 | 99 | int columnindex = 0; | ||
414 | 100 | for (const int key : items_table->keys<int>()) { | 98 | for (const int key : items_table->keys<int>()) { |
415 | 101 | std::vector<DescriptionIndex> column; | 99 | std::vector<DescriptionIndex> column; |
416 | 102 | std::vector<std::string> warenames = | 100 | std::vector<std::string> warenames = |
417 | @@ -110,7 +108,6 @@ | |||
418 | 110 | } | 108 | } |
419 | 111 | wares_.insert(wareindex); | 109 | wares_.insert(wareindex); |
420 | 112 | column.push_back(wareindex); | 110 | column.push_back(wareindex); |
421 | 113 | wares_order_coords_[wareindex] = std::make_pair(columnindex, rowindex); | ||
422 | 114 | } catch (const WException& e) { | 111 | } catch (const WException& e) { |
423 | 115 | throw GameDataError( | 112 | throw GameDataError( |
424 | 116 | "Failed adding ware '%s: %s", warenames[rowindex].c_str(), e.what()); | 113 | "Failed adding ware '%s: %s", warenames[rowindex].c_str(), e.what()); |
425 | @@ -118,13 +115,10 @@ | |||
426 | 118 | } | 115 | } |
427 | 119 | if (!column.empty()) { | 116 | if (!column.empty()) { |
428 | 120 | wares_order_.push_back(column); | 117 | wares_order_.push_back(column); |
429 | 121 | ++columnindex; | ||
430 | 122 | } | 118 | } |
431 | 123 | } | 119 | } |
432 | 124 | 120 | ||
433 | 125 | items_table = table.get_table("workers_order"); | 121 | items_table = table.get_table("workers_order"); |
434 | 126 | workers_order_coords_.resize(tribes_.nrworkers()); | ||
435 | 127 | columnindex = 0; | ||
436 | 128 | for (const int key : items_table->keys<int>()) { | 122 | for (const int key : items_table->keys<int>()) { |
437 | 129 | std::vector<DescriptionIndex> column; | 123 | std::vector<DescriptionIndex> column; |
438 | 130 | std::vector<std::string> workernames = | 124 | std::vector<std::string> workernames = |
439 | @@ -138,7 +132,6 @@ | |||
440 | 138 | } | 132 | } |
441 | 139 | workers_.insert(workerindex); | 133 | workers_.insert(workerindex); |
442 | 140 | column.push_back(workerindex); | 134 | column.push_back(workerindex); |
443 | 141 | workers_order_coords_[workerindex] = std::make_pair(columnindex, rowindex); | ||
444 | 142 | 135 | ||
445 | 143 | const WorkerDescr& worker_descr = *tribes_.get_worker_descr(workerindex); | 136 | const WorkerDescr& worker_descr = *tribes_.get_worker_descr(workerindex); |
446 | 144 | if (worker_descr.is_buildable() && worker_descr.buildcost().empty()) { | 137 | if (worker_descr.is_buildable() && worker_descr.buildcost().empty()) { |
447 | @@ -151,7 +144,6 @@ | |||
448 | 151 | } | 144 | } |
449 | 152 | if (!column.empty()) { | 145 | if (!column.empty()) { |
450 | 153 | workers_order_.push_back(column); | 146 | workers_order_.push_back(column); |
451 | 154 | ++columnindex; | ||
452 | 155 | } | 147 | } |
453 | 156 | } | 148 | } |
454 | 157 | 149 | ||
455 | @@ -424,38 +416,6 @@ | |||
456 | 424 | return list->second.find(lowest)->second; | 416 | return list->second.find(lowest)->second; |
457 | 425 | } | 417 | } |
458 | 426 | 418 | ||
459 | 427 | void TribeDescr::resize_ware_orders(size_t maxLength) { | ||
460 | 428 | bool need_resize = false; | ||
461 | 429 | |||
462 | 430 | // Check if we actually need to resize. | ||
463 | 431 | for (WaresOrder::iterator it = wares_order_.begin(); it != wares_order_.end(); ++it) { | ||
464 | 432 | if (it->size() > maxLength) { | ||
465 | 433 | need_resize = true; | ||
466 | 434 | } | ||
467 | 435 | } | ||
468 | 436 | |||
469 | 437 | // Build new smaller wares_order. | ||
470 | 438 | if (need_resize) { | ||
471 | 439 | WaresOrder new_wares_order; | ||
472 | 440 | for (WaresOrder::iterator it = wares_order_.begin(); it != wares_order_.end(); ++it) { | ||
473 | 441 | new_wares_order.push_back(std::vector<Widelands::DescriptionIndex>()); | ||
474 | 442 | for (std::vector<Widelands::DescriptionIndex>::iterator it2 = it->begin(); | ||
475 | 443 | it2 != it->end(); ++it2) { | ||
476 | 444 | if (new_wares_order.rbegin()->size() >= maxLength) { | ||
477 | 445 | new_wares_order.push_back(std::vector<Widelands::DescriptionIndex>()); | ||
478 | 446 | } | ||
479 | 447 | new_wares_order.rbegin()->push_back(*it2); | ||
480 | 448 | wares_order_coords_[*it2].first = new_wares_order.size() - 1; | ||
481 | 449 | wares_order_coords_[*it2].second = new_wares_order.rbegin()->size() - 1; | ||
482 | 450 | } | ||
483 | 451 | } | ||
484 | 452 | |||
485 | 453 | // Remove old array. | ||
486 | 454 | wares_order_.clear(); | ||
487 | 455 | wares_order_ = new_wares_order; | ||
488 | 456 | } | ||
489 | 457 | } | ||
490 | 458 | |||
491 | 459 | void TribeDescr::add_building(const std::string& buildingname) { | 419 | void TribeDescr::add_building(const std::string& buildingname) { |
492 | 460 | try { | 420 | try { |
493 | 461 | DescriptionIndex index = tribes_.safe_building_index(buildingname); | 421 | DescriptionIndex index = tribes_.safe_building_index(buildingname); |
494 | 462 | 422 | ||
495 | === modified file 'src/logic/map_objects/tribes/tribe_descr.h' | |||
496 | --- src/logic/map_objects/tribes/tribe_descr.h 2019-05-18 13:33:00 +0000 | |||
497 | +++ src/logic/map_objects/tribes/tribe_descr.h 2019-05-29 06:43:44 +0000 | |||
498 | @@ -148,22 +148,13 @@ | |||
499 | 148 | } | 148 | } |
500 | 149 | 149 | ||
501 | 150 | using WaresOrder = std::vector<std::vector<Widelands::DescriptionIndex>>; | 150 | using WaresOrder = std::vector<std::vector<Widelands::DescriptionIndex>>; |
502 | 151 | using WaresOrderCoords = std::vector<std::pair<uint32_t, uint32_t>>; | ||
503 | 152 | const WaresOrder& wares_order() const { | 151 | const WaresOrder& wares_order() const { |
504 | 153 | return wares_order_; | 152 | return wares_order_; |
505 | 154 | } | 153 | } |
506 | 155 | const WaresOrderCoords& wares_order_coords() const { | ||
507 | 156 | return wares_order_coords_; | ||
508 | 157 | } | ||
509 | 158 | 154 | ||
510 | 159 | const WaresOrder& workers_order() const { | 155 | const WaresOrder& workers_order() const { |
511 | 160 | return workers_order_; | 156 | return workers_order_; |
512 | 161 | } | 157 | } |
513 | 162 | const WaresOrderCoords& workers_order_coords() const { | ||
514 | 163 | return workers_order_coords_; | ||
515 | 164 | } | ||
516 | 165 | |||
517 | 166 | void resize_ware_orders(size_t maxLength); | ||
518 | 167 | 158 | ||
519 | 168 | const std::vector<std::string>& get_ship_names() const { | 159 | const std::vector<std::string>& get_ship_names() const { |
520 | 169 | return ship_names_; | 160 | return ship_names_; |
521 | @@ -213,9 +204,7 @@ | |||
522 | 213 | std::vector<DescriptionIndex> trainingsites_; | 204 | std::vector<DescriptionIndex> trainingsites_; |
523 | 214 | // Order and positioning of wares in the warehouse display | 205 | // Order and positioning of wares in the warehouse display |
524 | 215 | WaresOrder wares_order_; | 206 | WaresOrder wares_order_; |
525 | 216 | WaresOrderCoords wares_order_coords_; | ||
526 | 217 | WaresOrder workers_order_; | 207 | WaresOrder workers_order_; |
527 | 218 | WaresOrderCoords workers_order_coords_; | ||
528 | 219 | 208 | ||
529 | 220 | std::vector<Widelands::TribeBasicInfo::Initialization> initializations_; | 209 | std::vector<Widelands::TribeBasicInfo::Initialization> initializations_; |
530 | 221 | 210 | ||
531 | 222 | 211 | ||
532 | === modified file 'src/logic/map_objects/tribes/tribes.cc' | |||
533 | --- src/logic/map_objects/tribes/tribes.cc 2019-05-22 11:23:14 +0000 | |||
534 | +++ src/logic/map_objects/tribes/tribes.cc 2019-05-29 06:43:44 +0000 | |||
535 | @@ -347,14 +347,9 @@ | |||
536 | 347 | // Calculate the trainingsites proportions. | 347 | // Calculate the trainingsites proportions. |
537 | 348 | postload_calculate_trainingsites_proportions(); | 348 | postload_calculate_trainingsites_proportions(); |
538 | 349 | 349 | ||
543 | 350 | // Resize the configuration of our wares if they won't fit in the current window (12 = info label | 350 | // Some final checks on the gamedata |
540 | 351 | // size). | ||
541 | 352 | // Also, do some final checks on the gamedata | ||
542 | 353 | int number = (g_gr->get_yres() - 290) / (WARE_MENU_PIC_HEIGHT + WARE_MENU_PIC_PAD_Y + 12); | ||
544 | 354 | for (DescriptionIndex i = 0; i < tribes_->size(); ++i) { | 351 | for (DescriptionIndex i = 0; i < tribes_->size(); ++i) { |
545 | 355 | TribeDescr* tribe_descr = tribes_->get_mutable(i); | 352 | TribeDescr* tribe_descr = tribes_->get_mutable(i); |
546 | 356 | tribe_descr->resize_ware_orders(number); | ||
547 | 357 | |||
548 | 358 | // Verify that the preciousness has been set for all of the tribe's wares | 353 | // Verify that the preciousness has been set for all of the tribe's wares |
549 | 359 | for (const DescriptionIndex wi : tribe_descr->wares()) { | 354 | for (const DescriptionIndex wi : tribe_descr->wares()) { |
550 | 360 | if (tribe_descr->get_ware_descr(wi)->ai_hints().preciousness(tribe_descr->name()) == | 355 | if (tribe_descr->get_ware_descr(wi)->ai_hints().preciousness(tribe_descr->name()) == |
551 | 361 | 356 | ||
552 | === modified file 'src/logic/map_objects/tribes/ware_descr.h' | |||
553 | --- src/logic/map_objects/tribes/ware_descr.h 2019-05-22 11:23:14 +0000 | |||
554 | +++ src/logic/map_objects/tribes/ware_descr.h 2019-05-29 06:43:44 +0000 | |||
555 | @@ -35,10 +35,8 @@ | |||
556 | 35 | class Image; | 35 | class Image; |
557 | 36 | class LuaTable; | 36 | class LuaTable; |
558 | 37 | 37 | ||
563 | 38 | #define WARE_MENU_PIC_WIDTH 24 //!< Default width for ware's menu icons | 38 | constexpr int kWareMenuPicWidth = 24; //!< Default width for ware's menu icons |
564 | 39 | #define WARE_MENU_PIC_HEIGHT 24 //!< Default height for ware's menu icons | 39 | constexpr int kWareMenuPicHeight = 24; //!< Default height for ware's menu icons |
561 | 40 | #define WARE_MENU_PIC_PAD_X 3 //!< Default padding between menu icons | ||
562 | 41 | #define WARE_MENU_PIC_PAD_Y 4 //!< Default padding between menu icons | ||
565 | 42 | 40 | ||
566 | 43 | namespace Widelands { | 41 | namespace Widelands { |
567 | 44 | 42 | ||
568 | 45 | 43 | ||
569 | === modified file 'src/logic/playercommand.h' | |||
570 | --- src/logic/playercommand.h 2019-05-07 12:14:02 +0000 | |||
571 | +++ src/logic/playercommand.h 2019-05-29 06:43:44 +0000 | |||
572 | @@ -581,6 +581,7 @@ | |||
573 | 581 | uint32_t permanent_; | 581 | uint32_t permanent_; |
574 | 582 | }; | 582 | }; |
575 | 583 | 583 | ||
576 | 584 | // TODO(Nordfriese): CmdResetWareTargetQuantity can be removed when we next break savegame compatibility | ||
577 | 584 | struct CmdResetWareTargetQuantity : public CmdChangeTargetQuantity { | 585 | struct CmdResetWareTargetQuantity : public CmdChangeTargetQuantity { |
578 | 585 | CmdResetWareTargetQuantity() : CmdChangeTargetQuantity() { | 586 | CmdResetWareTargetQuantity() : CmdChangeTargetQuantity() { |
579 | 586 | } | 587 | } |
580 | @@ -629,6 +630,7 @@ | |||
581 | 629 | uint32_t permanent_; | 630 | uint32_t permanent_; |
582 | 630 | }; | 631 | }; |
583 | 631 | 632 | ||
584 | 633 | // TODO(Nordfriese): CmdResetWorkerTargetQuantity can be removed when we next break savegame compatibility | ||
585 | 632 | struct CmdResetWorkerTargetQuantity : public CmdChangeTargetQuantity { | 634 | struct CmdResetWorkerTargetQuantity : public CmdChangeTargetQuantity { |
586 | 633 | CmdResetWorkerTargetQuantity() : CmdChangeTargetQuantity() { | 635 | CmdResetWorkerTargetQuantity() : CmdChangeTargetQuantity() { |
587 | 634 | } | 636 | } |
588 | 635 | 637 | ||
589 | === modified file 'src/notifications/note_ids.h' | |||
590 | --- src/notifications/note_ids.h 2019-02-23 11:00:49 +0000 | |||
591 | +++ src/notifications/note_ids.h 2019-05-29 06:43:44 +0000 | |||
592 | @@ -36,6 +36,7 @@ | |||
593 | 36 | Ship, | 36 | Ship, |
594 | 37 | Building, | 37 | Building, |
595 | 38 | Economy, | 38 | Economy, |
596 | 39 | EconomyProfile, | ||
597 | 39 | GraphicResolutionChanged, | 40 | GraphicResolutionChanged, |
598 | 40 | NoteExpeditionCanceled, | 41 | NoteExpeditionCanceled, |
599 | 41 | Sound, | 42 | Sound, |
600 | 42 | 43 | ||
601 | === modified file 'src/wui/CMakeLists.txt' | |||
602 | --- src/wui/CMakeLists.txt 2019-05-12 07:45:59 +0000 | |||
603 | +++ src/wui/CMakeLists.txt 2019-05-29 06:43:44 +0000 | |||
604 | @@ -46,8 +46,10 @@ | |||
605 | 46 | graphic | 46 | graphic |
606 | 47 | logic | 47 | logic |
607 | 48 | logic_commands | 48 | logic_commands |
608 | 49 | logic_filesystem_constants | ||
609 | 49 | logic_map_objects | 50 | logic_map_objects |
610 | 50 | notifications | 51 | notifications |
611 | 52 | profile | ||
612 | 51 | ui_basic | 53 | ui_basic |
613 | 52 | wui_waresdisplay | 54 | wui_waresdisplay |
614 | 53 | ) | 55 | ) |
615 | 54 | 56 | ||
616 | === modified file 'src/wui/economy_options_window.cc' | |||
617 | --- src/wui/economy_options_window.cc 2019-05-01 07:20:25 +0000 | |||
618 | +++ src/wui/economy_options_window.cc 2019-05-29 06:43:44 +0000 | |||
619 | @@ -19,36 +19,104 @@ | |||
620 | 19 | 19 | ||
621 | 20 | #include "wui/economy_options_window.h" | 20 | #include "wui/economy_options_window.h" |
622 | 21 | 21 | ||
623 | 22 | #include <memory> | ||
624 | 23 | |||
625 | 22 | #include <boost/lexical_cast.hpp> | 24 | #include <boost/lexical_cast.hpp> |
626 | 23 | 25 | ||
627 | 24 | #include "graphic/graphic.h" | 26 | #include "graphic/graphic.h" |
628 | 25 | #include "logic/editor_game_base.h" | 27 | #include "logic/editor_game_base.h" |
629 | 28 | #include "logic/filesystem_constants.h" | ||
630 | 26 | #include "logic/map_objects/tribes/ware_descr.h" | 29 | #include "logic/map_objects/tribes/ware_descr.h" |
631 | 27 | #include "logic/map_objects/tribes/worker_descr.h" | 30 | #include "logic/map_objects/tribes/worker_descr.h" |
632 | 28 | #include "logic/player.h" | 31 | #include "logic/player.h" |
633 | 29 | #include "logic/playercommand.h" | 32 | #include "logic/playercommand.h" |
635 | 30 | #include "ui_basic/button.h" | 33 | #include "profile/profile.h" |
636 | 34 | #include "ui_basic/messagebox.h" | ||
637 | 31 | 35 | ||
638 | 32 | static const char pic_tab_wares[] = "images/wui/buildings/menu_tab_wares.png"; | 36 | static const char pic_tab_wares[] = "images/wui/buildings/menu_tab_wares.png"; |
639 | 33 | static const char pic_tab_workers[] = "images/wui/buildings/menu_tab_workers.png"; | 37 | static const char pic_tab_workers[] = "images/wui/buildings/menu_tab_workers.png"; |
640 | 34 | 38 | ||
641 | 39 | constexpr int kDesiredWidth = 216; | ||
642 | 40 | |||
643 | 35 | EconomyOptionsWindow::EconomyOptionsWindow(UI::Panel* parent, | 41 | EconomyOptionsWindow::EconomyOptionsWindow(UI::Panel* parent, |
644 | 36 | Widelands::Economy* economy, | 42 | Widelands::Economy* economy, |
645 | 37 | bool can_act) | 43 | bool can_act) |
646 | 38 | : UI::Window(parent, "economy_options", 0, 0, 0, 0, _("Economy options")), | 44 | : UI::Window(parent, "economy_options", 0, 0, 0, 0, _("Economy options")), |
647 | 45 | main_box_(this, 0, 0, UI::Box::Vertical), | ||
648 | 39 | serial_(economy->serial()), | 46 | serial_(economy->serial()), |
649 | 40 | player_(&economy->owner()), | 47 | player_(&economy->owner()), |
650 | 41 | tabpanel_(this, UI::TabPanelStyle::kWuiDark), | 48 | tabpanel_(this, UI::TabPanelStyle::kWuiDark), |
652 | 42 | ware_panel_(new EconomyOptionsPanel(&tabpanel_, serial_, player_, can_act, Widelands::wwWARE)), | 49 | ware_panel_(new EconomyOptionsPanel(&tabpanel_, this, serial_, player_, can_act, Widelands::wwWARE, kDesiredWidth)), |
653 | 43 | worker_panel_( | 50 | worker_panel_( |
656 | 44 | new EconomyOptionsPanel(&tabpanel_, serial_, player_, can_act, Widelands::wwWORKER)) { | 51 | new EconomyOptionsPanel(&tabpanel_, this, serial_, player_, can_act, Widelands::wwWORKER, kDesiredWidth)), |
657 | 45 | set_center_panel(&tabpanel_); | 52 | dropdown_box_(this, 0, 0, UI::Box::Horizontal), |
658 | 53 | dropdown_(&dropdown_box_, 0, 0, 174, 200, 34, "", UI::DropdownType::kTextual, UI::PanelStyle::kWui), | ||
659 | 54 | time_last_thought_(0), | ||
660 | 55 | save_profile_dialog_(nullptr) { | ||
661 | 56 | set_center_panel(&main_box_); | ||
662 | 46 | 57 | ||
663 | 47 | tabpanel_.add("wares", g_gr->images().get(pic_tab_wares), ware_panel_, _("Wares")); | 58 | tabpanel_.add("wares", g_gr->images().get(pic_tab_wares), ware_panel_, _("Wares")); |
664 | 48 | tabpanel_.add("workers", g_gr->images().get(pic_tab_workers), worker_panel_, _("Workers")); | 59 | tabpanel_.add("workers", g_gr->images().get(pic_tab_workers), worker_panel_, _("Workers")); |
665 | 60 | |||
666 | 61 | UI::Box* buttons = new UI::Box(this, 0, 0, UI::Box::Horizontal); | ||
667 | 62 | UI::Button* b = new UI::Button(buttons, "decrease_target_fast", 0, 0, 44, 28, UI::ButtonStyle::kWuiSecondary, | ||
668 | 63 | g_gr->images().get("images/ui_basic/scrollbar_down_fast.png"), _("Decrease target by 10")); | ||
669 | 64 | b->sigclicked.connect([this] { change_target(-10); }); | ||
670 | 65 | buttons->add(b); | ||
671 | 66 | b->set_repeating(true); | ||
672 | 67 | buttons->add_space(8); | ||
673 | 68 | b = new UI::Button(buttons, "decrease_target", 0, 0, 44, 28, UI::ButtonStyle::kWuiSecondary, | ||
674 | 69 | g_gr->images().get("images/ui_basic/scrollbar_down.png"), _("Decrease target")); | ||
675 | 70 | b->sigclicked.connect([this] { change_target(-1); }); | ||
676 | 71 | buttons->add(b); | ||
677 | 72 | b->set_repeating(true); | ||
678 | 73 | buttons->add_space(24); | ||
679 | 74 | |||
680 | 75 | b = new UI::Button(buttons, "increase_target", 0, 0, 44, 28, UI::ButtonStyle::kWuiSecondary, | ||
681 | 76 | g_gr->images().get("images/ui_basic/scrollbar_up.png"), _("Increase target")); | ||
682 | 77 | b->sigclicked.connect([this] { change_target(1); }); | ||
683 | 78 | buttons->add(b); | ||
684 | 79 | b->set_repeating(true); | ||
685 | 80 | buttons->add_space(8); | ||
686 | 81 | b = new UI::Button(buttons, "increase_target_fast", 0, 0, 44, 28, UI::ButtonStyle::kWuiSecondary, | ||
687 | 82 | g_gr->images().get("images/ui_basic/scrollbar_up_fast.png"), _("Increase target by 10")); | ||
688 | 83 | b->sigclicked.connect([this] { change_target(10); }); | ||
689 | 84 | buttons->add(b); | ||
690 | 85 | b->set_repeating(true); | ||
691 | 86 | |||
692 | 87 | dropdown_.set_tooltip(_("Profile to apply to the selected items")); | ||
693 | 88 | dropdown_box_.set_size(40, 20); // Prevent assert failures | ||
694 | 89 | dropdown_box_.add(&dropdown_, UI::Box::Resizing::kFullSize); | ||
695 | 90 | dropdown_.selected.connect([this] { reset_target(); }); | ||
696 | 91 | |||
697 | 92 | b = new UI::Button(&dropdown_box_, "save_targets", 0, 0, 34, 34, UI::ButtonStyle::kWuiMenu, | ||
698 | 93 | g_gr->images().get("images/wui/menus/menu_save_game.png"), _("Save target settings")); | ||
699 | 94 | b->sigclicked.connect([this] { create_target(); }); | ||
700 | 95 | dropdown_box_.add_space(8); | ||
701 | 96 | dropdown_box_.add(b); | ||
702 | 97 | |||
703 | 98 | main_box_.add(&tabpanel_, UI::Box::Resizing::kAlign, UI::Align::kCenter); | ||
704 | 99 | main_box_.add_space(8); | ||
705 | 100 | main_box_.add(buttons, UI::Box::Resizing::kAlign, UI::Align::kCenter); | ||
706 | 101 | main_box_.add_space(8); | ||
707 | 102 | main_box_.add(&dropdown_box_, UI::Box::Resizing::kAlign, UI::Align::kCenter); | ||
708 | 103 | |||
709 | 49 | economy->set_has_window(true); | 104 | economy->set_has_window(true); |
710 | 50 | economynotes_subscriber_ = Notifications::subscribe<Widelands::NoteEconomy>( | 105 | economynotes_subscriber_ = Notifications::subscribe<Widelands::NoteEconomy>( |
711 | 51 | [this](const Widelands::NoteEconomy& note) { on_economy_note(note); }); | 106 | [this](const Widelands::NoteEconomy& note) { on_economy_note(note); }); |
712 | 107 | profilenotes_subscriber_ = Notifications::subscribe<NoteEconomyProfile>( | ||
713 | 108 | [this](const NoteEconomyProfile& n) { | ||
714 | 109 | if (n.serial == serial_) { | ||
715 | 110 | // We already updated ourself before we changed something | ||
716 | 111 | return; | ||
717 | 112 | } | ||
718 | 113 | read_targets(); | ||
719 | 114 | if (save_profile_dialog_) { | ||
720 | 115 | save_profile_dialog_->update_table(); | ||
721 | 116 | } | ||
722 | 117 | }); | ||
723 | 118 | |||
724 | 119 | read_targets(); | ||
725 | 52 | } | 120 | } |
726 | 53 | 121 | ||
727 | 54 | EconomyOptionsWindow::~EconomyOptionsWindow() { | 122 | EconomyOptionsWindow::~EconomyOptionsWindow() { |
728 | @@ -56,6 +124,9 @@ | |||
729 | 56 | if (economy != nullptr) { | 124 | if (economy != nullptr) { |
730 | 57 | economy->set_has_window(false); | 125 | economy->set_has_window(false); |
731 | 58 | } | 126 | } |
732 | 127 | if (save_profile_dialog_) { | ||
733 | 128 | save_profile_dialog_->unset_parent(); | ||
734 | 129 | } | ||
735 | 59 | } | 130 | } |
736 | 60 | 131 | ||
737 | 61 | void EconomyOptionsWindow::on_economy_note(const Widelands::NoteEconomy& note) { | 132 | void EconomyOptionsWindow::on_economy_note(const Widelands::NoteEconomy& note) { |
738 | @@ -81,6 +152,20 @@ | |||
739 | 81 | } | 152 | } |
740 | 82 | } | 153 | } |
741 | 83 | 154 | ||
742 | 155 | void EconomyOptionsWindow::layout() { | ||
743 | 156 | int w, h; | ||
744 | 157 | tabpanel_.get_desired_size(&w, &h); | ||
745 | 158 | main_box_.set_desired_size(w, h + 78); | ||
746 | 159 | update_desired_size(); | ||
747 | 160 | UI::Window::layout(); | ||
748 | 161 | } | ||
749 | 162 | |||
750 | 163 | void EconomyOptionsWindow::EconomyOptionsPanel::update_desired_size() { | ||
751 | 164 | display_.set_hgap(AbstractWaresDisplay::calc_hgap(display_.get_extent().w, kDesiredWidth)); | ||
752 | 165 | Box::update_desired_size(); | ||
753 | 166 | get_parent()->layout(); | ||
754 | 167 | } | ||
755 | 168 | |||
756 | 84 | EconomyOptionsWindow::TargetWaresDisplay::TargetWaresDisplay(UI::Panel* const parent, | 169 | EconomyOptionsWindow::TargetWaresDisplay::TargetWaresDisplay(UI::Panel* const parent, |
757 | 85 | int32_t const x, | 170 | int32_t const x, |
758 | 86 | int32_t const y, | 171 | int32_t const y, |
759 | @@ -129,42 +214,26 @@ | |||
760 | 129 | * Wraps the wares/workers display together with some buttons | 214 | * Wraps the wares/workers display together with some buttons |
761 | 130 | */ | 215 | */ |
762 | 131 | EconomyOptionsWindow::EconomyOptionsPanel::EconomyOptionsPanel(UI::Panel* parent, | 216 | EconomyOptionsWindow::EconomyOptionsPanel::EconomyOptionsPanel(UI::Panel* parent, |
763 | 217 | EconomyOptionsWindow* eco_window, | ||
764 | 132 | Widelands::Serial serial, | 218 | Widelands::Serial serial, |
765 | 133 | Widelands::Player* player, | 219 | Widelands::Player* player, |
766 | 134 | bool can_act, | 220 | bool can_act, |
768 | 135 | Widelands::WareWorker type) | 221 | Widelands::WareWorker type, |
769 | 222 | int32_t min_w) | ||
770 | 136 | : UI::Box(parent, 0, 0, UI::Box::Vertical), | 223 | : UI::Box(parent, 0, 0, UI::Box::Vertical), |
771 | 137 | serial_(serial), | 224 | serial_(serial), |
772 | 138 | player_(player), | 225 | player_(player), |
773 | 139 | type_(type), | 226 | type_(type), |
774 | 140 | can_act_(can_act), | 227 | can_act_(can_act), |
776 | 141 | display_(this, 0, 0, serial_, player_, type_, can_act_) { | 228 | display_(this, 0, 0, serial_, player_, type_, can_act_), |
777 | 229 | economy_options_window_(eco_window) { | ||
778 | 142 | add(&display_, UI::Box::Resizing::kFullSize); | 230 | add(&display_, UI::Box::Resizing::kFullSize); |
779 | 143 | 231 | ||
780 | 232 | display_.set_hgap(AbstractWaresDisplay::calc_hgap(display_.get_extent().w, min_w)); | ||
781 | 233 | |||
782 | 144 | if (!can_act_) { | 234 | if (!can_act_) { |
783 | 145 | return; | 235 | return; |
784 | 146 | } | 236 | } |
785 | 147 | UI::Box* buttons = new UI::Box(this, 0, 0, UI::Box::Horizontal); | ||
786 | 148 | add(buttons); | ||
787 | 149 | |||
788 | 150 | UI::Button* b = new UI::Button(buttons, "decrease_target", 0, 0, 34, 34, | ||
789 | 151 | UI::ButtonStyle::kWuiMenu, "-", _("Decrease target")); | ||
790 | 152 | b->sigclicked.connect(boost::bind(&EconomyOptionsPanel::change_target, this, -1)); | ||
791 | 153 | buttons->add(b); | ||
792 | 154 | b->set_repeating(true); | ||
793 | 155 | buttons->add_space(8); | ||
794 | 156 | |||
795 | 157 | b = new UI::Button(buttons, "increase_target", 0, 0, 34, 34, UI::ButtonStyle::kWuiMenu, "+", | ||
796 | 158 | _("Increase target")); | ||
797 | 159 | b->sigclicked.connect(boost::bind(&EconomyOptionsPanel::change_target, this, 1)); | ||
798 | 160 | buttons->add(b); | ||
799 | 161 | b->set_repeating(true); | ||
800 | 162 | buttons->add_space(8); | ||
801 | 163 | |||
802 | 164 | b = new UI::Button( | ||
803 | 165 | buttons, "reset_target", 0, 0, 34, 34, UI::ButtonStyle::kWuiMenu, "R", _("Reset to default")); | ||
804 | 166 | b->sigclicked.connect(boost::bind(&EconomyOptionsPanel::reset_target, this)); | ||
805 | 167 | buttons->add(b); | ||
806 | 168 | } | 237 | } |
807 | 169 | 238 | ||
808 | 170 | void EconomyOptionsWindow::EconomyOptionsPanel::set_economy(Widelands::Serial serial) { | 239 | void EconomyOptionsWindow::EconomyOptionsPanel::set_economy(Widelands::Serial serial) { |
809 | @@ -172,7 +241,29 @@ | |||
810 | 172 | display_.set_economy(serial); | 241 | display_.set_economy(serial); |
811 | 173 | } | 242 | } |
812 | 174 | 243 | ||
814 | 175 | void EconomyOptionsWindow::EconomyOptionsPanel::change_target(int amount) { | 244 | void EconomyOptionsWindow::change_target(int amount) { |
815 | 245 | if (tabpanel_.active() == 0) { | ||
816 | 246 | ware_panel_->change_target(amount); | ||
817 | 247 | } else { | ||
818 | 248 | worker_panel_->change_target(amount); | ||
819 | 249 | } | ||
820 | 250 | } | ||
821 | 251 | |||
822 | 252 | void EconomyOptionsWindow::reset_target() { | ||
823 | 253 | if (dropdown_.get_selected().empty()) { | ||
824 | 254 | return; | ||
825 | 255 | } | ||
826 | 256 | if (tabpanel_.active() == 0) { | ||
827 | 257 | ware_panel_->reset_target(); | ||
828 | 258 | } else { | ||
829 | 259 | worker_panel_->reset_target(); | ||
830 | 260 | } | ||
831 | 261 | } | ||
832 | 262 | |||
833 | 263 | void EconomyOptionsWindow::EconomyOptionsPanel::change_target(int delta) { | ||
834 | 264 | if (delta == 0) { | ||
835 | 265 | return; | ||
836 | 266 | } | ||
837 | 176 | Widelands::Economy* economy = player_->get_economy(serial_); | 267 | Widelands::Economy* economy = player_->get_economy(serial_); |
838 | 177 | if (economy == nullptr) { | 268 | if (economy == nullptr) { |
839 | 178 | die(); | 269 | die(); |
840 | @@ -186,35 +277,401 @@ | |||
841 | 186 | const Widelands::Economy::TargetQuantity& tq = is_wares ? | 277 | const Widelands::Economy::TargetQuantity& tq = is_wares ? |
842 | 187 | economy->ware_target_quantity(index) : | 278 | economy->ware_target_quantity(index) : |
843 | 188 | economy->worker_target_quantity(index); | 279 | economy->worker_target_quantity(index); |
846 | 189 | // Don't allow negative new amount. | 280 | // Don't allow negative new amount |
847 | 190 | if (amount >= 0 || -amount <= static_cast<int>(tq.permanent)) { | 281 | const int old_amount = static_cast<int>(tq.permanent); |
848 | 282 | const int new_amount = std::max(0, old_amount + delta); | ||
849 | 283 | if (new_amount == old_amount) { | ||
850 | 284 | continue; | ||
851 | 285 | } | ||
852 | 286 | if (is_wares) { | ||
853 | 287 | game.send_player_command(new Widelands::CmdSetWareTargetQuantity( | ||
854 | 288 | game.get_gametime(), player_->player_number(), serial_, index, new_amount)); | ||
855 | 289 | } else { | ||
856 | 290 | game.send_player_command(new Widelands::CmdSetWorkerTargetQuantity( | ||
857 | 291 | game.get_gametime(), player_->player_number(), serial_, index, new_amount)); | ||
858 | 292 | } | ||
859 | 293 | } | ||
860 | 294 | } | ||
861 | 295 | } | ||
862 | 296 | |||
863 | 297 | void EconomyOptionsWindow::EconomyOptionsPanel::reset_target() { | ||
864 | 298 | Widelands::Game& game = dynamic_cast<Widelands::Game&>(player_->egbase()); | ||
865 | 299 | const bool is_wares = type_ == Widelands::wwWARE; | ||
866 | 300 | const auto& items = is_wares ? player_->tribe().wares() : player_->tribe().workers(); | ||
867 | 301 | const PredefinedTargets settings = economy_options_window_->get_selected_target(); | ||
868 | 302 | |||
869 | 303 | bool anything_selected = false; | ||
870 | 304 | bool second_phase = false; | ||
871 | 305 | |||
872 | 306 | do { | ||
873 | 307 | for (const Widelands::DescriptionIndex& index : items) { | ||
874 | 308 | if (display_.ware_selected(index) || (second_phase && !display_.is_ware_hidden(index))) { | ||
875 | 309 | anything_selected = true; | ||
876 | 191 | if (is_wares) { | 310 | if (is_wares) { |
877 | 192 | game.send_player_command(new Widelands::CmdSetWareTargetQuantity( | 311 | game.send_player_command(new Widelands::CmdSetWareTargetQuantity( |
880 | 193 | game.get_gametime(), player_->player_number(), serial_, index, | 312 | game.get_gametime(), player_->player_number(), serial_, index, settings.wares.at(index))); |
879 | 194 | tq.permanent + amount)); | ||
881 | 195 | } else { | 313 | } else { |
882 | 196 | game.send_player_command(new Widelands::CmdSetWorkerTargetQuantity( | 314 | game.send_player_command(new Widelands::CmdSetWorkerTargetQuantity( |
906 | 197 | game.get_gametime(), player_->player_number(), serial_, index, | 315 | game.get_gametime(), player_->player_number(), serial_, index, settings.workers.at(index))); |
907 | 198 | tq.permanent + amount)); | 316 | } |
908 | 199 | } | 317 | } |
909 | 200 | } | 318 | } |
910 | 201 | } | 319 | if (anything_selected) { |
911 | 202 | } | 320 | return; |
912 | 203 | } | 321 | } |
913 | 204 | 322 | // Nothing was selected, now go through the loop again and change everything | |
914 | 205 | void EconomyOptionsWindow::EconomyOptionsPanel::reset_target() { | 323 | second_phase = true; |
915 | 206 | Widelands::Game& game = dynamic_cast<Widelands::Game&>(player_->egbase()); | 324 | } while (!second_phase); |
916 | 207 | const bool is_wares = type_ == Widelands::wwWARE; | 325 | } |
917 | 208 | const auto& items = is_wares ? player_->tribe().wares() : player_->tribe().workers(); | 326 | |
918 | 209 | for (const Widelands::DescriptionIndex& index : items) { | 327 | constexpr unsigned kThinkInterval = 200; |
919 | 210 | if (display_.ware_selected(index)) { | 328 | |
920 | 211 | if (is_wares) { | 329 | void EconomyOptionsWindow::think() { |
921 | 212 | game.send_player_command(new Widelands::CmdResetWareTargetQuantity( | 330 | const uint32_t time = player_->egbase().get_gametime(); |
922 | 213 | game.get_gametime(), player_->player_number(), serial_, index)); | 331 | if (time - time_last_thought_ < kThinkInterval || !player_->get_economy(serial_)) { |
923 | 214 | } else { | 332 | // If our economy has been deleted, die() was already called, no need to do anything |
924 | 215 | game.send_player_command(new Widelands::CmdResetWorkerTargetQuantity( | 333 | return; |
925 | 216 | game.get_gametime(), player_->player_number(), serial_, index)); | 334 | } |
926 | 217 | } | 335 | time_last_thought_ = time; |
927 | 218 | } | 336 | update_profiles(); |
928 | 219 | } | 337 | } |
929 | 338 | |||
930 | 339 | std::string EconomyOptionsWindow::applicable_target() { | ||
931 | 340 | const Widelands::Economy* eco = player_->get_economy(serial_); | ||
932 | 341 | for (const auto& pair : predefined_targets_) { | ||
933 | 342 | bool matches = true; | ||
934 | 343 | if (tabpanel_.active() == 0) { | ||
935 | 344 | for (const Widelands::DescriptionIndex& index : player_->tribe().wares()) { | ||
936 | 345 | const auto it = pair.second.wares.find(index); | ||
937 | 346 | if (it != pair.second.wares.end() && eco->ware_target_quantity(index).permanent != it->second) { | ||
938 | 347 | matches = false; | ||
939 | 348 | break; | ||
940 | 349 | } | ||
941 | 350 | } | ||
942 | 351 | } else { | ||
943 | 352 | for (const Widelands::DescriptionIndex& index : player_->tribe().workers()) { | ||
944 | 353 | const auto it = pair.second.workers.find(index); | ||
945 | 354 | if (it != pair.second.workers.end() && eco->worker_target_quantity(index).permanent != it->second) { | ||
946 | 355 | matches = false; | ||
947 | 356 | break; | ||
948 | 357 | } | ||
949 | 358 | } | ||
950 | 359 | } | ||
951 | 360 | if (matches) { | ||
952 | 361 | return pair.first; | ||
953 | 362 | } | ||
954 | 363 | } | ||
955 | 364 | return ""; | ||
956 | 365 | } | ||
957 | 366 | |||
958 | 367 | void EconomyOptionsWindow::update_profiles() { | ||
959 | 368 | const std::string current_profile = applicable_target(); | ||
960 | 369 | |||
961 | 370 | for (const auto& pair : predefined_targets_) { | ||
962 | 371 | if (last_added_to_dropdown_.count(pair.first) == 0) { | ||
963 | 372 | return update_profiles_needed(current_profile); | ||
964 | 373 | } | ||
965 | 374 | } | ||
966 | 375 | for (const auto& string : last_added_to_dropdown_) { | ||
967 | 376 | if (!string.empty() && predefined_targets_.find(string) == predefined_targets_.end()) { | ||
968 | 377 | return update_profiles_needed(current_profile); | ||
969 | 378 | } | ||
970 | 379 | } | ||
971 | 380 | if (last_added_to_dropdown_.count("") == (current_profile.empty() ? 0 : 1)) { | ||
972 | 381 | return update_profiles_needed(current_profile); | ||
973 | 382 | } | ||
974 | 383 | |||
975 | 384 | update_profiles_select(current_profile); | ||
976 | 385 | } | ||
977 | 386 | |||
978 | 387 | void EconomyOptionsWindow::update_profiles_needed(const std::string& current_profile) { | ||
979 | 388 | dropdown_.clear(); | ||
980 | 389 | last_added_to_dropdown_.clear(); | ||
981 | 390 | for (const auto& pair : predefined_targets_) { | ||
982 | 391 | dropdown_.add(_(pair.first), pair.first); | ||
983 | 392 | last_added_to_dropdown_.insert(pair.first); | ||
984 | 393 | } | ||
985 | 394 | if (current_profile.empty()) { | ||
986 | 395 | // Nothing selected | ||
987 | 396 | dropdown_.add("–", ""); | ||
988 | 397 | last_added_to_dropdown_.insert(""); | ||
989 | 398 | } | ||
990 | 399 | update_profiles_select(current_profile); | ||
991 | 400 | } | ||
992 | 401 | |||
993 | 402 | void EconomyOptionsWindow::update_profiles_select(const std::string& current_profile) { | ||
994 | 403 | if (dropdown_.is_expanded()) { | ||
995 | 404 | return; | ||
996 | 405 | } | ||
997 | 406 | if (!dropdown_.has_selection() || dropdown_.get_selected() != current_profile) { | ||
998 | 407 | dropdown_.select(current_profile); | ||
999 | 408 | } | ||
1000 | 409 | assert(dropdown_.has_selection()); | ||
1001 | 410 | } | ||
1002 | 411 | |||
1003 | 412 | void EconomyOptionsWindow::SaveProfileWindow::update_save_enabled() { | ||
1004 | 413 | const std::string& text = profile_name_.text(); | ||
1005 | 414 | if (text.empty() || text == kDefaultEconomyProfile) { | ||
1006 | 415 | save_.set_enabled(false); | ||
1007 | 416 | save_.set_tooltip(text.empty() ? _("The profile name cannot be empty") : | ||
1008 | 417 | _("The default profile cannot be overwritten")); | ||
1009 | 418 | } else { | ||
1010 | 419 | save_.set_enabled(true); | ||
1011 | 420 | save_.set_tooltip(_("Save the profile under this name")); | ||
1012 | 421 | } | ||
1013 | 422 | } | ||
1014 | 423 | |||
1015 | 424 | void EconomyOptionsWindow::SaveProfileWindow::table_selection_changed() { | ||
1016 | 425 | if (!table_.has_selection()) { | ||
1017 | 426 | delete_.set_enabled(false); | ||
1018 | 427 | delete_.set_tooltip(""); | ||
1019 | 428 | return; | ||
1020 | 429 | } | ||
1021 | 430 | const std::string& sel = table_[table_.selection_index()]; | ||
1022 | 431 | if (economy_options_->get_predefined_targets().at(sel).undeletable) { | ||
1023 | 432 | delete_.set_tooltip(_("The predefined profiles cannot be deleted")); | ||
1024 | 433 | delete_.set_enabled(false); | ||
1025 | 434 | } else { | ||
1026 | 435 | delete_.set_tooltip(_("Delete the selected profiles")); | ||
1027 | 436 | delete_.set_enabled(true); | ||
1028 | 437 | } | ||
1029 | 438 | profile_name_.set_text(sel); | ||
1030 | 439 | update_save_enabled(); | ||
1031 | 440 | } | ||
1032 | 441 | |||
1033 | 442 | void EconomyOptionsWindow::SaveProfileWindow::update_table() { | ||
1034 | 443 | table_.clear(); | ||
1035 | 444 | for (const auto& pair : economy_options_->get_predefined_targets()) { | ||
1036 | 445 | table_.add(pair.first).set_string(0, _(pair.first)); | ||
1037 | 446 | } | ||
1038 | 447 | layout(); | ||
1039 | 448 | } | ||
1040 | 449 | |||
1041 | 450 | void EconomyOptionsWindow::SaveProfileWindow::save() { | ||
1042 | 451 | const std::string name = profile_name_.text(); | ||
1043 | 452 | assert(!name.empty()); | ||
1044 | 453 | assert(name != kDefaultEconomyProfile); | ||
1045 | 454 | for (const auto& pair : economy_options_->get_predefined_targets()) { | ||
1046 | 455 | if (pair.first == name) { | ||
1047 | 456 | UI::WLMessageBox m(this, _("Overwrite?"), | ||
1048 | 457 | _("A profile with this name already exists. Do you wish to replace it?"), | ||
1049 | 458 | UI::WLMessageBox::MBoxType::kOkCancel); | ||
1050 | 459 | if (m.run<UI::Panel::Returncodes>() != UI::Panel::Returncodes::kOk) { | ||
1051 | 460 | return; | ||
1052 | 461 | } | ||
1053 | 462 | break; | ||
1054 | 463 | } | ||
1055 | 464 | } | ||
1056 | 465 | economy_options_->do_create_target(name); | ||
1057 | 466 | die(); | ||
1058 | 467 | } | ||
1059 | 468 | |||
1060 | 469 | void EconomyOptionsWindow::SaveProfileWindow::delete_selected() { | ||
1061 | 470 | assert(table_.has_selection()); | ||
1062 | 471 | |||
1063 | 472 | auto& map = economy_options_->get_predefined_targets(); | ||
1064 | 473 | const std::string& name = table_[table_.selection_index()]; | ||
1065 | 474 | |||
1066 | 475 | assert(name != kDefaultEconomyProfile); | ||
1067 | 476 | assert(!map.at(name).undeletable); | ||
1068 | 477 | auto it = map.find(name); | ||
1069 | 478 | assert(it != map.end()); | ||
1070 | 479 | map.erase(it); | ||
1071 | 480 | |||
1072 | 481 | economy_options_->save_targets(); | ||
1073 | 482 | economy_options_->update_profiles(); | ||
1074 | 483 | update_table(); | ||
1075 | 484 | } | ||
1076 | 485 | |||
1077 | 486 | void EconomyOptionsWindow::SaveProfileWindow::unset_parent() { | ||
1078 | 487 | economy_options_ = nullptr; | ||
1079 | 488 | die(); | ||
1080 | 489 | } | ||
1081 | 490 | |||
1082 | 491 | void EconomyOptionsWindow::SaveProfileWindow::think() { | ||
1083 | 492 | if (!economy_options_) { | ||
1084 | 493 | die(); | ||
1085 | 494 | } | ||
1086 | 495 | UI::Window::think(); | ||
1087 | 496 | } | ||
1088 | 497 | |||
1089 | 498 | EconomyOptionsWindow::SaveProfileWindow::SaveProfileWindow(UI::Panel* parent, EconomyOptionsWindow* eco) | ||
1090 | 499 | : UI::Window(parent, "save_economy_options_profile", 0, 0, 0, 0, _("Save Profile")), | ||
1091 | 500 | economy_options_(eco), | ||
1092 | 501 | main_box_(this, 0, 0, UI::Box::Vertical), | ||
1093 | 502 | table_box_(&main_box_, 0, 0, UI::Box::Vertical), | ||
1094 | 503 | table_(&table_box_, 0, 0, 460, 120, UI::PanelStyle::kWui), | ||
1095 | 504 | buttons_box_(&main_box_, 0, 0, UI::Box::Horizontal), | ||
1096 | 505 | profile_name_(&buttons_box_, 0, 0, 240, UI::PanelStyle::kWui), | ||
1097 | 506 | save_(&buttons_box_, "save", 0, 0, 80, 34, UI::ButtonStyle::kWuiPrimary, _("Save")), | ||
1098 | 507 | cancel_(&buttons_box_, "cancel", 0, 0, 80, 34, UI::ButtonStyle::kWuiSecondary, _("Cancel")), | ||
1099 | 508 | delete_(&buttons_box_, "delete", 0, 0, 80, 34, UI::ButtonStyle::kWuiSecondary, _("Delete")) { | ||
1100 | 509 | table_.add_column(200, _("Existing Profiles")); | ||
1101 | 510 | update_table(); | ||
1102 | 511 | |||
1103 | 512 | table_.selected.connect([this](uint32_t) { table_selection_changed(); }); | ||
1104 | 513 | profile_name_.changed.connect([this] { update_save_enabled(); }); | ||
1105 | 514 | profile_name_.ok.connect([this] { save(); }); | ||
1106 | 515 | profile_name_.cancel.connect([this] { die(); }); | ||
1107 | 516 | save_.sigclicked.connect([this] { save(); }); | ||
1108 | 517 | cancel_.sigclicked.connect([this] { die(); }); | ||
1109 | 518 | delete_.sigclicked.connect([this] { delete_selected(); }); | ||
1110 | 519 | |||
1111 | 520 | table_box_.add(&table_, UI::Box::Resizing::kFullSize); | ||
1112 | 521 | buttons_box_.add(&profile_name_, UI::Box::Resizing::kFullSize); | ||
1113 | 522 | buttons_box_.add(&save_); | ||
1114 | 523 | buttons_box_.add(&cancel_); | ||
1115 | 524 | buttons_box_.add(&delete_); | ||
1116 | 525 | main_box_.add(&table_box_, UI::Box::Resizing::kFullSize); | ||
1117 | 526 | main_box_.add(&buttons_box_, UI::Box::Resizing::kFullSize); | ||
1118 | 527 | set_center_panel(&main_box_); | ||
1119 | 528 | |||
1120 | 529 | table_selection_changed(); | ||
1121 | 530 | update_save_enabled(); | ||
1122 | 531 | } | ||
1123 | 532 | |||
1124 | 533 | EconomyOptionsWindow::SaveProfileWindow::~SaveProfileWindow() { | ||
1125 | 534 | if (economy_options_) { | ||
1126 | 535 | economy_options_->close_save_profile_window(); | ||
1127 | 536 | } | ||
1128 | 537 | } | ||
1129 | 538 | |||
1130 | 539 | void EconomyOptionsWindow::create_target() { | ||
1131 | 540 | if (save_profile_dialog_) { | ||
1132 | 541 | // Already open | ||
1133 | 542 | return; | ||
1134 | 543 | } | ||
1135 | 544 | save_profile_dialog_ = new SaveProfileWindow(get_parent(), this); | ||
1136 | 545 | } | ||
1137 | 546 | |||
1138 | 547 | void EconomyOptionsWindow::close_save_profile_window() { | ||
1139 | 548 | assert(save_profile_dialog_); | ||
1140 | 549 | save_profile_dialog_ = nullptr; | ||
1141 | 550 | } | ||
1142 | 551 | |||
1143 | 552 | void EconomyOptionsWindow::do_create_target(const std::string& name) { | ||
1144 | 553 | assert(!name.empty()); | ||
1145 | 554 | assert(name != kDefaultEconomyProfile); | ||
1146 | 555 | const Widelands::Tribes& tribes = player_->egbase().tribes(); | ||
1147 | 556 | const Widelands::TribeDescr& tribe = player_->tribe(); | ||
1148 | 557 | Widelands::Economy* economy = player_->get_economy(serial_); | ||
1149 | 558 | PredefinedTargets t; | ||
1150 | 559 | for (Widelands::DescriptionIndex di : tribe.wares()) { | ||
1151 | 560 | if (tribes.get_ware_descr(di)->has_demand_check(tribe.name())) { | ||
1152 | 561 | t.wares[di] = economy->ware_target_quantity(di).permanent; | ||
1153 | 562 | } | ||
1154 | 563 | } | ||
1155 | 564 | for (Widelands::DescriptionIndex di : tribe.workers()) { | ||
1156 | 565 | if (tribes.get_worker_descr(di)->has_demand_check()) { | ||
1157 | 566 | t.workers[di] = economy->worker_target_quantity(di).permanent; | ||
1158 | 567 | } | ||
1159 | 568 | } | ||
1160 | 569 | predefined_targets_[name] = t; | ||
1161 | 570 | |||
1162 | 571 | save_targets(); | ||
1163 | 572 | update_profiles(); | ||
1164 | 573 | } | ||
1165 | 574 | |||
1166 | 575 | void EconomyOptionsWindow::save_targets() { | ||
1167 | 576 | const Widelands::Tribes& tribes = player_->egbase().tribes(); | ||
1168 | 577 | Profile profile; | ||
1169 | 578 | |||
1170 | 579 | std::map<std::string, uint32_t> serials; | ||
1171 | 580 | for (const auto& pair : predefined_targets_) { | ||
1172 | 581 | if (pair.first != kDefaultEconomyProfile) { | ||
1173 | 582 | serials.insert(std::make_pair(pair.first, serials.size())); | ||
1174 | 583 | } | ||
1175 | 584 | } | ||
1176 | 585 | Section& global_section = profile.create_section(kDefaultEconomyProfile.c_str()); | ||
1177 | 586 | for (const auto& pair : serials) { | ||
1178 | 587 | global_section.set_string(std::to_string(pair.second).c_str(), pair.first); | ||
1179 | 588 | } | ||
1180 | 589 | |||
1181 | 590 | for (const auto& pair : predefined_targets_) { | ||
1182 | 591 | if (pair.first == kDefaultEconomyProfile) { | ||
1183 | 592 | continue; | ||
1184 | 593 | } | ||
1185 | 594 | Section& section = profile.create_section(std::to_string(serials.at(pair.first)).c_str()); | ||
1186 | 595 | for (const auto& setting : pair.second.wares) { | ||
1187 | 596 | section.set_natural(tribes.get_ware_descr(setting.first)->name().c_str(), setting.second); | ||
1188 | 597 | } | ||
1189 | 598 | for (const auto& setting : pair.second.workers) { | ||
1190 | 599 | section.set_natural(tribes.get_worker_descr(setting.first)->name().c_str(), setting.second); | ||
1191 | 600 | } | ||
1192 | 601 | } | ||
1193 | 602 | |||
1194 | 603 | Section& section = profile.create_section("undeletable"); | ||
1195 | 604 | for (const auto& pair : predefined_targets_) { | ||
1196 | 605 | if (pair.first != kDefaultEconomyProfile) { | ||
1197 | 606 | section.set_bool(std::to_string(serials.at(pair.first)).c_str(), pair.second.undeletable); | ||
1198 | 607 | } | ||
1199 | 608 | } | ||
1200 | 609 | |||
1201 | 610 | g_fs->ensure_directory_exists(kEconomyProfilesDir); | ||
1202 | 611 | std::string complete_filename = kEconomyProfilesDir + g_fs->file_separator() + player_->tribe().name(); | ||
1203 | 612 | profile.write(complete_filename.c_str(), false); | ||
1204 | 613 | |||
1205 | 614 | // Inform the windows of other economies of new and deleted profiles | ||
1206 | 615 | Notifications::publish(NoteEconomyProfile(serial_)); | ||
1207 | 616 | } | ||
1208 | 617 | |||
1209 | 618 | void EconomyOptionsWindow::read_targets() { | ||
1210 | 619 | predefined_targets_.clear(); | ||
1211 | 620 | const Widelands::Tribes& tribes = player_->egbase().tribes(); | ||
1212 | 621 | const Widelands::TribeDescr& tribe = player_->tribe(); | ||
1213 | 622 | |||
1214 | 623 | { | ||
1215 | 624 | PredefinedTargets t; | ||
1216 | 625 | t.undeletable = true; | ||
1217 | 626 | for (Widelands::DescriptionIndex di : tribe.wares()) { | ||
1218 | 627 | const Widelands::WareDescr* descr = tribes.get_ware_descr(di); | ||
1219 | 628 | if (descr->has_demand_check(tribe.name())) { | ||
1220 | 629 | t.wares.insert(std::make_pair(di, descr->default_target_quantity(tribe.name()))); | ||
1221 | 630 | } | ||
1222 | 631 | } | ||
1223 | 632 | for (Widelands::DescriptionIndex di : tribe.workers()) { | ||
1224 | 633 | const Widelands::WorkerDescr* descr = tribes.get_worker_descr(di); | ||
1225 | 634 | if (descr->has_demand_check()) { | ||
1226 | 635 | t.workers.insert(std::make_pair(di, descr->default_target_quantity())); | ||
1227 | 636 | } | ||
1228 | 637 | } | ||
1229 | 638 | predefined_targets_.insert(std::make_pair(kDefaultEconomyProfile, t)); | ||
1230 | 639 | } | ||
1231 | 640 | |||
1232 | 641 | std::string complete_filename = kEconomyProfilesDir + g_fs->file_separator() + player_->tribe().name(); | ||
1233 | 642 | Profile profile; | ||
1234 | 643 | profile.read(complete_filename.c_str()); | ||
1235 | 644 | |||
1236 | 645 | Section* global_section = profile.get_section(kDefaultEconomyProfile); | ||
1237 | 646 | if (global_section) { | ||
1238 | 647 | std::map<std::string, std::string> serials; | ||
1239 | 648 | while (Section::Value* v = global_section->get_next_val()) { | ||
1240 | 649 | serials.insert(std::make_pair(v->get_name(), v->get_string())); | ||
1241 | 650 | } | ||
1242 | 651 | |||
1243 | 652 | for (const auto& pair : serials) { | ||
1244 | 653 | Section* section = profile.get_section(pair.first); | ||
1245 | 654 | PredefinedTargets t; | ||
1246 | 655 | while (Section::Value* v = section->get_next_val()) { | ||
1247 | 656 | const std::string name(v->get_name()); | ||
1248 | 657 | Widelands::DescriptionIndex di = tribes.ware_index(name); | ||
1249 | 658 | if (di == Widelands::INVALID_INDEX) { | ||
1250 | 659 | di = tribes.worker_index(name); | ||
1251 | 660 | assert(di != Widelands::INVALID_INDEX); | ||
1252 | 661 | t.workers.insert(std::make_pair(di, v->get_natural())); | ||
1253 | 662 | } else { | ||
1254 | 663 | t.wares.insert(std::make_pair(di, v->get_natural())); | ||
1255 | 664 | } | ||
1256 | 665 | } | ||
1257 | 666 | predefined_targets_.insert(std::make_pair(pair.second, t)); | ||
1258 | 667 | } | ||
1259 | 668 | |||
1260 | 669 | if (Section* section = profile.get_section("undeletable")) { | ||
1261 | 670 | while (Section::Value* v = section->get_next_val()) { | ||
1262 | 671 | predefined_targets_.at(serials.at(std::string(v->get_name()))).undeletable = v->get_bool(); | ||
1263 | 672 | } | ||
1264 | 673 | } | ||
1265 | 674 | } | ||
1266 | 675 | |||
1267 | 676 | update_profiles(); | ||
1268 | 220 | } | 677 | } |
1269 | 221 | 678 | ||
1270 | === modified file 'src/wui/economy_options_window.h' | |||
1271 | --- src/wui/economy_options_window.h 2019-02-23 11:00:49 +0000 | |||
1272 | +++ src/wui/economy_options_window.h 2019-05-29 06:43:44 +0000 | |||
1273 | @@ -20,19 +20,61 @@ | |||
1274 | 20 | #ifndef WL_WUI_ECONOMY_OPTIONS_WINDOW_H | 20 | #ifndef WL_WUI_ECONOMY_OPTIONS_WINDOW_H |
1275 | 21 | #define WL_WUI_ECONOMY_OPTIONS_WINDOW_H | 21 | #define WL_WUI_ECONOMY_OPTIONS_WINDOW_H |
1276 | 22 | 22 | ||
1277 | 23 | #include <map> | ||
1278 | 23 | #include <memory> | 24 | #include <memory> |
1279 | 25 | #include <string> | ||
1280 | 24 | 26 | ||
1281 | 25 | #include "economy/economy.h" | 27 | #include "economy/economy.h" |
1282 | 26 | #include "logic/map_objects/tribes/tribe_descr.h" | 28 | #include "logic/map_objects/tribes/tribe_descr.h" |
1283 | 27 | #include "notifications/notifications.h" | 29 | #include "notifications/notifications.h" |
1284 | 28 | #include "ui_basic/box.h" | 30 | #include "ui_basic/box.h" |
1285 | 31 | #include "ui_basic/button.h" | ||
1286 | 32 | #include "ui_basic/dropdown.h" | ||
1287 | 33 | #include "ui_basic/editbox.h" | ||
1288 | 34 | #include "ui_basic/table.h" | ||
1289 | 29 | #include "ui_basic/tabpanel.h" | 35 | #include "ui_basic/tabpanel.h" |
1290 | 30 | #include "ui_basic/window.h" | 36 | #include "ui_basic/window.h" |
1291 | 31 | #include "wui/waresdisplay.h" | 37 | #include "wui/waresdisplay.h" |
1292 | 32 | 38 | ||
1293 | 39 | const std::string kDefaultEconomyProfile = "Default"; | ||
1294 | 40 | |||
1295 | 41 | // Used to indicate that a profile has been saved or deleted, so all open windows can update it | ||
1296 | 42 | struct NoteEconomyProfile { | ||
1297 | 43 | NoteEconomyProfile(Widelands::Serial s) : serial(s) { | ||
1298 | 44 | } | ||
1299 | 45 | Widelands::Serial serial; | ||
1300 | 46 | CAN_BE_SENT_AS_NOTE(NoteId::EconomyProfile) | ||
1301 | 47 | }; | ||
1302 | 48 | |||
1303 | 33 | struct EconomyOptionsWindow : public UI::Window { | 49 | struct EconomyOptionsWindow : public UI::Window { |
1304 | 34 | EconomyOptionsWindow(UI::Panel* parent, Widelands::Economy* economy, bool can_act); | 50 | EconomyOptionsWindow(UI::Panel* parent, Widelands::Economy* economy, bool can_act); |
1306 | 35 | ~EconomyOptionsWindow(); | 51 | ~EconomyOptionsWindow() override; |
1307 | 52 | |||
1308 | 53 | struct PredefinedTargets { | ||
1309 | 54 | using Targets = std::map<Widelands::DescriptionIndex, uint32_t>; | ||
1310 | 55 | Targets wares; | ||
1311 | 56 | Targets workers; | ||
1312 | 57 | bool undeletable = false; | ||
1313 | 58 | }; | ||
1314 | 59 | |||
1315 | 60 | void create_target(); | ||
1316 | 61 | void do_create_target(const std::string&); | ||
1317 | 62 | void save_targets(); | ||
1318 | 63 | void read_targets(); | ||
1319 | 64 | void update_profiles(); | ||
1320 | 65 | std::map<std::string, PredefinedTargets>& get_predefined_targets() { | ||
1321 | 66 | return predefined_targets_; | ||
1322 | 67 | } | ||
1323 | 68 | const PredefinedTargets& get_selected_target() const { | ||
1324 | 69 | return predefined_targets_.at(dropdown_.get_selected()); | ||
1325 | 70 | } | ||
1326 | 71 | |||
1327 | 72 | void change_target(int amount); | ||
1328 | 73 | void reset_target(); | ||
1329 | 74 | |||
1330 | 75 | void layout() override; | ||
1331 | 76 | |||
1332 | 77 | void close_save_profile_window(); | ||
1333 | 36 | 78 | ||
1334 | 37 | private: | 79 | private: |
1335 | 38 | struct TargetWaresDisplay : public AbstractWaresDisplay { | 80 | struct TargetWaresDisplay : public AbstractWaresDisplay { |
1336 | @@ -59,14 +101,17 @@ | |||
1337 | 59 | */ | 101 | */ |
1338 | 60 | struct EconomyOptionsPanel : UI::Box { | 102 | struct EconomyOptionsPanel : UI::Box { |
1339 | 61 | EconomyOptionsPanel(UI::Panel* parent, | 103 | EconomyOptionsPanel(UI::Panel* parent, |
1340 | 104 | EconomyOptionsWindow* eco_window, | ||
1341 | 62 | Widelands::Serial serial, | 105 | Widelands::Serial serial, |
1342 | 63 | Widelands::Player* player, | 106 | Widelands::Player* player, |
1343 | 64 | bool can_act, | 107 | bool can_act, |
1345 | 65 | Widelands::WareWorker type); | 108 | Widelands::WareWorker type, |
1346 | 109 | int32_t min_w); | ||
1347 | 66 | 110 | ||
1348 | 67 | void set_economy(Widelands::Serial serial); | 111 | void set_economy(Widelands::Serial serial); |
1349 | 68 | void change_target(int amount); | 112 | void change_target(int amount); |
1350 | 69 | void reset_target(); | 113 | void reset_target(); |
1351 | 114 | void update_desired_size() override; | ||
1352 | 70 | 115 | ||
1353 | 71 | private: | 116 | private: |
1354 | 72 | Widelands::Serial serial_; | 117 | Widelands::Serial serial_; |
1355 | @@ -74,17 +119,61 @@ | |||
1356 | 74 | Widelands::WareWorker type_; | 119 | Widelands::WareWorker type_; |
1357 | 75 | bool can_act_; | 120 | bool can_act_; |
1358 | 76 | TargetWaresDisplay display_; | 121 | TargetWaresDisplay display_; |
1359 | 122 | EconomyOptionsWindow* economy_options_window_; | ||
1360 | 77 | }; | 123 | }; |
1361 | 78 | 124 | ||
1362 | 79 | /// Actions performed when a NoteEconomyWindow is received. | 125 | /// Actions performed when a NoteEconomyWindow is received. |
1363 | 80 | void on_economy_note(const Widelands::NoteEconomy& note); | 126 | void on_economy_note(const Widelands::NoteEconomy& note); |
1364 | 81 | 127 | ||
1365 | 128 | UI::Box main_box_; | ||
1366 | 82 | Widelands::Serial serial_; | 129 | Widelands::Serial serial_; |
1367 | 83 | Widelands::Player* player_; | 130 | Widelands::Player* player_; |
1368 | 84 | UI::TabPanel tabpanel_; | 131 | UI::TabPanel tabpanel_; |
1369 | 85 | EconomyOptionsPanel* ware_panel_; | 132 | EconomyOptionsPanel* ware_panel_; |
1370 | 86 | EconomyOptionsPanel* worker_panel_; | 133 | EconomyOptionsPanel* worker_panel_; |
1371 | 87 | std::unique_ptr<Notifications::Subscriber<Widelands::NoteEconomy>> economynotes_subscriber_; | 134 | std::unique_ptr<Notifications::Subscriber<Widelands::NoteEconomy>> economynotes_subscriber_; |
1372 | 135 | std::unique_ptr<Notifications::Subscriber<NoteEconomyProfile>> profilenotes_subscriber_; | ||
1373 | 136 | |||
1374 | 137 | std::map<std::string, PredefinedTargets> predefined_targets_; | ||
1375 | 138 | UI::Box dropdown_box_; | ||
1376 | 139 | UI::Dropdown<std::string> dropdown_; | ||
1377 | 140 | |||
1378 | 141 | std::string applicable_target(); | ||
1379 | 142 | std::set<std::string> last_added_to_dropdown_; | ||
1380 | 143 | void think() override; | ||
1381 | 144 | uint32_t time_last_thought_; | ||
1382 | 145 | |||
1383 | 146 | struct SaveProfileWindow : public UI::Window { | ||
1384 | 147 | SaveProfileWindow(UI::Panel* parent, EconomyOptionsWindow* eco); | ||
1385 | 148 | ~SaveProfileWindow() override; | ||
1386 | 149 | |||
1387 | 150 | void update_save_enabled(); | ||
1388 | 151 | void table_selection_changed(); | ||
1389 | 152 | void update_table(); | ||
1390 | 153 | void save(); | ||
1391 | 154 | void delete_selected(); | ||
1392 | 155 | |||
1393 | 156 | void unset_parent(); | ||
1394 | 157 | |||
1395 | 158 | void think() override; | ||
1396 | 159 | |||
1397 | 160 | private: | ||
1398 | 161 | EconomyOptionsWindow* economy_options_; | ||
1399 | 162 | UI::Box main_box_; | ||
1400 | 163 | UI::Box table_box_; | ||
1401 | 164 | UI::Table<const std::string&> table_; | ||
1402 | 165 | UI::Box buttons_box_; | ||
1403 | 166 | UI::EditBox profile_name_; | ||
1404 | 167 | UI::Button save_; | ||
1405 | 168 | UI::Button cancel_; | ||
1406 | 169 | UI::Button delete_; | ||
1407 | 170 | }; | ||
1408 | 171 | |||
1409 | 172 | // Helper functions for update_profiles() | ||
1410 | 173 | void update_profiles_needed(const std::string&); | ||
1411 | 174 | void update_profiles_select(const std::string&); | ||
1412 | 175 | |||
1413 | 176 | SaveProfileWindow* save_profile_dialog_; | ||
1414 | 88 | }; | 177 | }; |
1415 | 89 | 178 | ||
1416 | 90 | #endif // end of include guard: WL_WUI_ECONOMY_OPTIONS_WINDOW_H | 179 | #endif // end of include guard: WL_WUI_ECONOMY_OPTIONS_WINDOW_H |
1417 | 91 | 180 | ||
1418 | === modified file 'src/wui/inputqueuedisplay.cc' | |||
1419 | --- src/wui/inputqueuedisplay.cc 2019-05-27 05:37:03 +0000 | |||
1420 | +++ src/wui/inputqueuedisplay.cc 2019-05-29 06:43:44 +0000 | |||
1421 | @@ -72,7 +72,7 @@ | |||
1422 | 72 | 72 | ||
1423 | 73 | uint32_t priority_button_height = show_only ? 0 : 3 * PriorityButtonSize; | 73 | uint32_t priority_button_height = show_only ? 0 : 3 * PriorityButtonSize; |
1424 | 74 | uint32_t image_height = | 74 | uint32_t image_height = |
1426 | 75 | show_only ? WARE_MENU_PIC_HEIGHT : std::max<int32_t>(WARE_MENU_PIC_HEIGHT, ph); | 75 | show_only ? kWareMenuPicHeight : std::max<int32_t>(kWareMenuPicHeight, ph); |
1427 | 76 | 76 | ||
1428 | 77 | total_height_ = std::max(priority_button_height, image_height) + 2 * Border; | 77 | total_height_ = std::max(priority_button_height, image_height) + 2 * Border; |
1429 | 78 | 78 | ||
1430 | @@ -92,7 +92,7 @@ | |||
1431 | 92 | */ | 92 | */ |
1432 | 93 | void InputQueueDisplay::max_size_changed() { | 93 | void InputQueueDisplay::max_size_changed() { |
1433 | 94 | uint32_t pbs = show_only_ ? 0 : PriorityButtonSize; | 94 | uint32_t pbs = show_only_ ? 0 : PriorityButtonSize; |
1435 | 95 | uint32_t ctrl_b_size = show_only_ ? 0 : 2 * WARE_MENU_PIC_WIDTH; | 95 | uint32_t ctrl_b_size = show_only_ ? 0 : 2 * kWareMenuPicWidth; |
1436 | 96 | 96 | ||
1437 | 97 | cache_size_ = queue_.get_max_size(); | 97 | cache_size_ = queue_.get_max_size(); |
1438 | 98 | 98 | ||
1439 | @@ -141,7 +141,7 @@ | |||
1440 | 141 | 141 | ||
1441 | 142 | Vector2i point = Vector2i::zero(); | 142 | Vector2i point = Vector2i::zero(); |
1442 | 143 | point.x = Border + (show_only_ ? 0 : CellWidth + CellSpacing); | 143 | point.x = Border + (show_only_ ? 0 : CellWidth + CellSpacing); |
1444 | 144 | point.y = Border + (total_height_ - 2 * Border - WARE_MENU_PIC_HEIGHT) / 2; | 144 | point.y = Border + (total_height_ - 2 * Border - kWareMenuPicHeight) / 2; |
1445 | 145 | 145 | ||
1446 | 146 | for (; nr_inputs_to_draw; --nr_inputs_to_draw, point.x += CellWidth + CellSpacing) { | 146 | for (; nr_inputs_to_draw; --nr_inputs_to_draw, point.x += CellWidth + CellSpacing) { |
1447 | 147 | dst.blitrect(Vector2i(point.x, point.y), icon_, Recti(0, 0, icon_->width(), icon_->height()), | 147 | dst.blitrect(Vector2i(point.x, point.y), icon_, Recti(0, 0, icon_->width(), icon_->height()), |
1448 | @@ -241,12 +241,12 @@ | |||
1449 | 241 | return; | 241 | return; |
1450 | 242 | 242 | ||
1451 | 243 | uint32_t x = Border; | 243 | uint32_t x = Border; |
1453 | 244 | uint32_t y = Border + (total_height_ - 2 * Border - WARE_MENU_PIC_WIDTH) / 2; | 244 | uint32_t y = Border + (total_height_ - 2 * Border - kWareMenuPicWidth) / 2; |
1454 | 245 | 245 | ||
1455 | 246 | boost::format tooltip_format("<p>%s%s%s</p>"); | 246 | boost::format tooltip_format("<p>%s%s%s</p>"); |
1456 | 247 | 247 | ||
1457 | 248 | decrease_max_fill_ = new UI::Button( | 248 | decrease_max_fill_ = new UI::Button( |
1459 | 249 | this, "decrease_max_fill", x, y, WARE_MENU_PIC_WIDTH, WARE_MENU_PIC_HEIGHT, | 249 | this, "decrease_max_fill", x, y, kWareMenuPicWidth, kWareMenuPicHeight, |
1460 | 250 | UI::ButtonStyle::kWuiMenu, g_gr->images().get("images/ui_basic/scrollbar_left.png"), | 250 | UI::ButtonStyle::kWuiMenu, g_gr->images().get("images/ui_basic/scrollbar_left.png"), |
1461 | 251 | (tooltip_format % | 251 | (tooltip_format % |
1462 | 252 | g_gr->styles() | 252 | g_gr->styles() |
1463 | @@ -272,7 +272,7 @@ | |||
1464 | 272 | x = Border + (cache_size_ + 1) * (CellWidth + CellSpacing); | 272 | x = Border + (cache_size_ + 1) * (CellWidth + CellSpacing); |
1465 | 273 | 273 | ||
1466 | 274 | increase_max_fill_ = new UI::Button( | 274 | increase_max_fill_ = new UI::Button( |
1468 | 275 | this, "increase_max_fill", x, y, WARE_MENU_PIC_WIDTH, WARE_MENU_PIC_HEIGHT, | 275 | this, "increase_max_fill", x, y, kWareMenuPicWidth, kWareMenuPicHeight, |
1469 | 276 | UI::ButtonStyle::kWuiMenu, g_gr->images().get("images/ui_basic/scrollbar_right.png"), | 276 | UI::ButtonStyle::kWuiMenu, g_gr->images().get("images/ui_basic/scrollbar_right.png"), |
1470 | 277 | (tooltip_format | 277 | (tooltip_format |
1471 | 278 | 278 | ||
1472 | 279 | 279 | ||
1473 | === modified file 'src/wui/inputqueuedisplay.h' | |||
1474 | --- src/wui/inputqueuedisplay.h 2019-04-23 14:53:35 +0000 | |||
1475 | +++ src/wui/inputqueuedisplay.h 2019-05-29 06:43:44 +0000 | |||
1476 | @@ -49,7 +49,7 @@ | |||
1477 | 49 | */ | 49 | */ |
1478 | 50 | class InputQueueDisplay : public UI::Panel { | 50 | class InputQueueDisplay : public UI::Panel { |
1479 | 51 | public: | 51 | public: |
1481 | 52 | enum { CellWidth = WARE_MENU_PIC_WIDTH, CellSpacing = 2, Border = 4, PriorityButtonSize = 10 }; | 52 | enum { CellWidth = kWareMenuPicWidth, CellSpacing = 2, Border = 4, PriorityButtonSize = 10 }; |
1482 | 53 | 53 | ||
1483 | 54 | InputQueueDisplay(UI::Panel* parent, | 54 | InputQueueDisplay(UI::Panel* parent, |
1484 | 55 | int32_t x, | 55 | int32_t x, |
1485 | 56 | 56 | ||
1486 | === modified file 'src/wui/ware_statistics_menu.cc' | |||
1487 | --- src/wui/ware_statistics_menu.cc 2019-03-26 22:15:39 +0000 | |||
1488 | +++ src/wui/ware_statistics_menu.cc 2019-05-29 06:43:44 +0000 | |||
1489 | @@ -22,6 +22,7 @@ | |||
1490 | 22 | #include "base/i18n.h" | 22 | #include "base/i18n.h" |
1491 | 23 | #include "graphic/graphic.h" | 23 | #include "graphic/graphic.h" |
1492 | 24 | #include "graphic/rendertarget.h" | 24 | #include "graphic/rendertarget.h" |
1493 | 25 | #include "graphic/text_layout.h" | ||
1494 | 25 | #include "logic/map_objects/tribes/tribe_descr.h" | 26 | #include "logic/map_objects/tribes/tribe_descr.h" |
1495 | 26 | #include "logic/map_objects/tribes/warelist.h" | 27 | #include "logic/map_objects/tribes/warelist.h" |
1496 | 27 | #include "logic/player.h" | 28 | #include "logic/player.h" |
1497 | @@ -101,7 +102,11 @@ | |||
1498 | 101 | ®istry, | 102 | ®istry, |
1499 | 102 | kPlotWidth + 2 * kSpacing, | 103 | kPlotWidth + 2 * kSpacing, |
1500 | 103 | 270, | 104 | 270, |
1502 | 104 | _("Ware Statistics")) { | 105 | _("Ware Statistics")), |
1503 | 106 | main_box_(nullptr), | ||
1504 | 107 | tab_panel_(nullptr), | ||
1505 | 108 | display_(nullptr), | ||
1506 | 109 | slider_(nullptr) { | ||
1507 | 105 | uint8_t const nr_wares = parent.get_player()->egbase().tribes().nrwares(); | 110 | uint8_t const nr_wares = parent.get_player()->egbase().tribes().nrwares(); |
1508 | 106 | 111 | ||
1509 | 107 | // Init color sets | 112 | // Init color sets |
1510 | @@ -111,45 +116,45 @@ | |||
1511 | 111 | std::fill(active_colors_.begin(), active_colors_.end(), 0); | 116 | std::fill(active_colors_.begin(), active_colors_.end(), 0); |
1512 | 112 | 117 | ||
1513 | 113 | // First, we must decide about the size. | 118 | // First, we must decide about the size. |
1517 | 114 | UI::Box* box = new UI::Box(this, 0, 0, UI::Box::Vertical, 0, 0, 5); | 119 | main_box_ = new UI::Box(this, 0, 0, UI::Box::Vertical, 0, 0, 5); |
1518 | 115 | box->set_border(kSpacing, kSpacing, kSpacing, kSpacing); | 120 | main_box_->set_border(kSpacing, kSpacing, kSpacing, kSpacing); |
1519 | 116 | set_center_panel(box); | 121 | set_center_panel(main_box_); |
1520 | 117 | 122 | ||
1521 | 118 | // Setup plot widgets | 123 | // Setup plot widgets |
1522 | 119 | // Create a tabbed environment for the different plots | 124 | // Create a tabbed environment for the different plots |
1524 | 120 | UI::TabPanel* tabs = new UI::TabPanel(box, UI::TabPanelStyle::kWuiDark); | 125 | tab_panel_ = new UI::TabPanel(main_box_, UI::TabPanelStyle::kWuiDark); |
1525 | 121 | 126 | ||
1526 | 122 | plot_production_ = | 127 | plot_production_ = |
1528 | 123 | new WuiPlotArea(tabs, 0, 0, kPlotWidth, kPlotHeight + kSpacing, | 128 | new WuiPlotArea(tab_panel_, 0, 0, kPlotWidth, kPlotHeight + kSpacing, |
1529 | 124 | Widelands::kStatisticsSampleTime, WuiPlotArea::Plotmode::kRelative); | 129 | Widelands::kStatisticsSampleTime, WuiPlotArea::Plotmode::kRelative); |
1530 | 125 | 130 | ||
1532 | 126 | tabs->add( | 131 | tab_panel_->add( |
1533 | 127 | "production", g_gr->images().get(pic_tab_production), plot_production_, _("Production")); | 132 | "production", g_gr->images().get(pic_tab_production), plot_production_, _("Production")); |
1534 | 128 | 133 | ||
1535 | 129 | plot_consumption_ = | 134 | plot_consumption_ = |
1537 | 130 | new WuiPlotArea(tabs, 0, 0, kPlotWidth, kPlotHeight + kSpacing, | 135 | new WuiPlotArea(tab_panel_, 0, 0, kPlotWidth, kPlotHeight + kSpacing, |
1538 | 131 | Widelands::kStatisticsSampleTime, WuiPlotArea::Plotmode::kRelative); | 136 | Widelands::kStatisticsSampleTime, WuiPlotArea::Plotmode::kRelative); |
1539 | 132 | 137 | ||
1541 | 133 | tabs->add( | 138 | tab_panel_->add( |
1542 | 134 | "consumption", g_gr->images().get(pic_tab_consumption), plot_consumption_, _("Consumption")); | 139 | "consumption", g_gr->images().get(pic_tab_consumption), plot_consumption_, _("Consumption")); |
1543 | 135 | 140 | ||
1544 | 136 | plot_economy_ = | 141 | plot_economy_ = |
1546 | 137 | new DifferentialPlotArea(tabs, 0, 0, kPlotWidth, kPlotHeight + kSpacing, | 142 | new DifferentialPlotArea(tab_panel_, 0, 0, kPlotWidth, kPlotHeight + kSpacing, |
1547 | 138 | Widelands::kStatisticsSampleTime, WuiPlotArea::Plotmode::kRelative); | 143 | Widelands::kStatisticsSampleTime, WuiPlotArea::Plotmode::kRelative); |
1548 | 139 | 144 | ||
1550 | 140 | tabs->add( | 145 | tab_panel_->add( |
1551 | 141 | "economy_health", g_gr->images().get(pic_tab_economy), plot_economy_, _("Economy health")); | 146 | "economy_health", g_gr->images().get(pic_tab_economy), plot_economy_, _("Economy health")); |
1552 | 142 | 147 | ||
1553 | 143 | plot_stock_ = | 148 | plot_stock_ = |
1555 | 144 | new WuiPlotArea(tabs, 0, 0, kPlotWidth, kPlotHeight + kSpacing, | 149 | new WuiPlotArea(tab_panel_, 0, 0, kPlotWidth, kPlotHeight + kSpacing, |
1556 | 145 | Widelands::kStatisticsSampleTime, WuiPlotArea::Plotmode::kAbsolute); | 150 | Widelands::kStatisticsSampleTime, WuiPlotArea::Plotmode::kAbsolute); |
1557 | 146 | 151 | ||
1559 | 147 | tabs->add("stock", g_gr->images().get(pic_tab_stock), plot_stock_, _("Stock")); | 152 | tab_panel_->add("stock", g_gr->images().get(pic_tab_stock), plot_stock_, _("Stock")); |
1560 | 148 | 153 | ||
1562 | 149 | tabs->activate(0); | 154 | tab_panel_->activate(0); |
1563 | 150 | 155 | ||
1564 | 151 | // Add tabbed environment to box | 156 | // Add tabbed environment to box |
1566 | 152 | box->add(tabs, UI::Box::Resizing::kFullSize); | 157 | main_box_->add(tab_panel_, UI::Box::Resizing::kFullSize); |
1567 | 153 | 158 | ||
1568 | 154 | // Register statistics data | 159 | // Register statistics data |
1569 | 155 | for (Widelands::DescriptionIndex cur_ware = 0; cur_ware < nr_wares; ++cur_ware) { | 160 | for (Widelands::DescriptionIndex cur_ware = 0; cur_ware < nr_wares; ++cur_ware) { |
1570 | @@ -178,15 +183,16 @@ | |||
1571 | 178 | colors[kInactiveColorIndex]); | 183 | colors[kInactiveColorIndex]); |
1572 | 179 | } | 184 | } |
1573 | 180 | 185 | ||
1576 | 181 | box->add(new StatisticWaresDisplay( | 186 | display_ = new StatisticWaresDisplay( |
1577 | 182 | box, 0, 0, parent.get_player()->tribe(), | 187 | main_box_, 0, 0, parent.get_player()->tribe(), |
1578 | 183 | [this](const int ware_index, const bool what) { cb_changed_to(ware_index, what); }, | 188 | [this](const int ware_index, const bool what) { cb_changed_to(ware_index, what); }, |
1581 | 184 | color_map_), | 189 | color_map_); |
1582 | 185 | UI::Box::Resizing::kFullSize); | 190 | display_->set_min_free_vertical_space(400); |
1583 | 191 | main_box_->add(display_, UI::Box::Resizing::kFullSize); | ||
1584 | 186 | 192 | ||
1588 | 187 | WuiPlotAreaSlider* slider = new WuiPlotAreaSlider(this, *plot_production_, 0, 0, kPlotWidth, 45); | 193 | slider_ = new WuiPlotAreaSlider(this, *plot_production_, 0, 0, kPlotWidth, 45); |
1589 | 188 | slider->changedto.connect([this](const int32_t timescale) { set_time(timescale); }); | 194 | slider_->changedto.connect([this](const int32_t timescale) { set_time(timescale); }); |
1590 | 189 | box->add(slider, UI::Box::Resizing::kFullSize); | 195 | main_box_->add(slider_, UI::Box::Resizing::kFullSize); |
1591 | 190 | } | 196 | } |
1592 | 191 | 197 | ||
1593 | 192 | /** | 198 | /** |
1594 | @@ -228,6 +234,27 @@ | |||
1595 | 228 | plot_stock_->show_plot(static_cast<size_t>(id), what); | 234 | plot_stock_->show_plot(static_cast<size_t>(id), what); |
1596 | 229 | } | 235 | } |
1597 | 230 | 236 | ||
1598 | 237 | static bool layouting = false; | ||
1599 | 238 | void WareStatisticsMenu::layout() { | ||
1600 | 239 | if (layouting || !tab_panel_ || !display_ || !slider_ || !main_box_) { | ||
1601 | 240 | return; | ||
1602 | 241 | } | ||
1603 | 242 | layouting = true; | ||
1604 | 243 | |||
1605 | 244 | display_->set_hgap(3, false); | ||
1606 | 245 | int w1, h1, w2, h2, w3, h3; | ||
1607 | 246 | tab_panel_->get_desired_size(&w1, &h1); | ||
1608 | 247 | display_->get_desired_size(&w2, &h2); | ||
1609 | 248 | slider_->get_desired_size(&w3, &h3); | ||
1610 | 249 | |||
1611 | 250 | display_->set_hgap(std::max(3, AbstractWaresDisplay::calc_hgap(display_->get_extent().w, kPlotWidth)), false); | ||
1612 | 251 | display_->get_desired_size(&w2, &h2); | ||
1613 | 252 | |||
1614 | 253 | main_box_->set_desired_size(std::max(w2, kPlotWidth) + 2 * kSpacing, h1 + h2 + h3 + text_height(UI::FontStyle::kLabel)); | ||
1615 | 254 | UI::UniqueWindow::layout(); | ||
1616 | 255 | layouting = false; | ||
1617 | 256 | } | ||
1618 | 257 | |||
1619 | 231 | /** | 258 | /** |
1620 | 232 | * Callback for the time buttons. Change the time axis of all ware | 259 | * Callback for the time buttons. Change the time axis of all ware |
1621 | 233 | * statistics simultaneously. | 260 | * statistics simultaneously. |
1622 | 234 | 261 | ||
1623 | === modified file 'src/wui/ware_statistics_menu.h' | |||
1624 | --- src/wui/ware_statistics_menu.h 2019-02-23 11:00:49 +0000 | |||
1625 | +++ src/wui/ware_statistics_menu.h 2019-05-29 06:43:44 +0000 | |||
1626 | @@ -29,13 +29,27 @@ | |||
1627 | 29 | struct DifferentialPlotArea; | 29 | struct DifferentialPlotArea; |
1628 | 30 | class InteractivePlayer; | 30 | class InteractivePlayer; |
1629 | 31 | struct WuiPlotArea; | 31 | struct WuiPlotArea; |
1630 | 32 | struct StatisticWaresDisplay; | ||
1631 | 33 | struct WuiPlotAreaSlider; | ||
1632 | 34 | namespace UI { | ||
1633 | 35 | struct Box; | ||
1634 | 36 | struct TabPanel; | ||
1635 | 37 | } | ||
1636 | 32 | 38 | ||
1637 | 33 | struct WareStatisticsMenu : public UI::UniqueWindow { | 39 | struct WareStatisticsMenu : public UI::UniqueWindow { |
1638 | 34 | public: | 40 | public: |
1639 | 35 | WareStatisticsMenu(InteractivePlayer&, UI::UniqueWindow::Registry&); | 41 | WareStatisticsMenu(InteractivePlayer&, UI::UniqueWindow::Registry&); |
1640 | 36 | void set_time(int32_t); | 42 | void set_time(int32_t); |
1641 | 37 | 43 | ||
1642 | 44 | protected: | ||
1643 | 45 | void layout() override; | ||
1644 | 46 | |||
1645 | 38 | private: | 47 | private: |
1646 | 48 | UI::Box* main_box_; | ||
1647 | 49 | UI::TabPanel* tab_panel_; | ||
1648 | 50 | StatisticWaresDisplay* display_; | ||
1649 | 51 | WuiPlotAreaSlider* slider_; | ||
1650 | 52 | |||
1651 | 39 | WuiPlotArea* plot_production_; | 53 | WuiPlotArea* plot_production_; |
1652 | 40 | WuiPlotArea* plot_consumption_; | 54 | WuiPlotArea* plot_consumption_; |
1653 | 41 | WuiPlotArea* plot_stock_; | 55 | WuiPlotArea* plot_stock_; |
1654 | 42 | 56 | ||
1655 | === modified file 'src/wui/waresdisplay.cc' | |||
1656 | --- src/wui/waresdisplay.cc 2019-05-26 17:21:15 +0000 | |||
1657 | +++ src/wui/waresdisplay.cc 2019-05-29 06:43:44 +0000 | |||
1658 | @@ -35,8 +35,9 @@ | |||
1659 | 35 | #include "logic/map_objects/tribes/ware_descr.h" | 35 | #include "logic/map_objects/tribes/ware_descr.h" |
1660 | 36 | #include "logic/map_objects/tribes/worker.h" | 36 | #include "logic/map_objects/tribes/worker.h" |
1661 | 37 | #include "logic/player.h" | 37 | #include "logic/player.h" |
1662 | 38 | #include "ui_basic/window.h" | ||
1663 | 38 | 39 | ||
1665 | 39 | const int WARE_MENU_INFO_SIZE = 12; | 40 | constexpr int kWareMenuInfoSize = 12; |
1666 | 40 | 41 | ||
1667 | 41 | AbstractWaresDisplay::AbstractWaresDisplay( | 42 | AbstractWaresDisplay::AbstractWaresDisplay( |
1668 | 42 | UI::Panel* const parent, | 43 | UI::Panel* const parent, |
1669 | @@ -46,7 +47,9 @@ | |||
1670 | 46 | Widelands::WareWorker type, | 47 | Widelands::WareWorker type, |
1671 | 47 | bool selectable, | 48 | bool selectable, |
1672 | 48 | boost::function<void(Widelands::DescriptionIndex, bool)> callback_function, | 49 | boost::function<void(Widelands::DescriptionIndex, bool)> callback_function, |
1674 | 49 | bool horizontal) | 50 | bool horizontal, |
1675 | 51 | int32_t hgap, | ||
1676 | 52 | int32_t vgap) | ||
1677 | 50 | : // Size is set when add_warelist is called, as it depends on the type_. | 53 | : // Size is set when add_warelist is called, as it depends on the type_. |
1678 | 51 | UI::Panel(parent, x, y, 0, 0), | 54 | UI::Panel(parent, x, y, 0, 0), |
1679 | 52 | tribe_(tribe), | 55 | tribe_(tribe), |
1680 | @@ -57,8 +60,11 @@ | |||
1681 | 57 | 60 | ||
1682 | 58 | selectable_(selectable), | 61 | selectable_(selectable), |
1683 | 59 | horizontal_(horizontal), | 62 | horizontal_(horizontal), |
1684 | 63 | hgap_(hgap), | ||
1685 | 64 | vgap_(vgap), | ||
1686 | 60 | selection_anchor_(Widelands::INVALID_INDEX), | 65 | selection_anchor_(Widelands::INVALID_INDEX), |
1688 | 61 | callback_function_(callback_function) { | 66 | callback_function_(callback_function), |
1689 | 67 | min_free_vertical_space_(290) { | ||
1690 | 62 | for (const Widelands::DescriptionIndex& index : indices_) { | 68 | for (const Widelands::DescriptionIndex& index : indices_) { |
1691 | 63 | selected_.insert(std::make_pair(index, false)); | 69 | selected_.insert(std::make_pair(index, false)); |
1692 | 64 | hidden_.insert(std::make_pair(index, false)); | 70 | hidden_.insert(std::make_pair(index, false)); |
1693 | @@ -67,22 +73,65 @@ | |||
1694 | 67 | 73 | ||
1695 | 68 | curware_.set_text(_("Stock")); | 74 | curware_.set_text(_("Stock")); |
1696 | 69 | 75 | ||
1703 | 70 | // Find out geometry from icons_order | 76 | graphic_resolution_changed_subscriber_ = Notifications::subscribe<GraphicResolutionChanged>( |
1704 | 71 | unsigned int columns = icons_order().size(); | 77 | [this](const GraphicResolutionChanged&) { |
1705 | 72 | unsigned int rows = 0; | 78 | recalc_desired_size(true); |
1706 | 73 | for (unsigned int i = 0; i < icons_order().size(); i++) | 79 | }); |
1707 | 74 | if (icons_order()[i].size() > rows) | 80 | |
1708 | 75 | rows = icons_order()[i].size(); | 81 | recalc_desired_size(false); |
1709 | 82 | } | ||
1710 | 83 | |||
1711 | 84 | Widelands::Extent AbstractWaresDisplay::get_extent() const { | ||
1712 | 85 | int16_t columns = 0; | ||
1713 | 86 | int16_t rows = 0; | ||
1714 | 87 | for (const auto& pair : icons_order_coords()) { | ||
1715 | 88 | columns = std::max(columns, pair.second.x); | ||
1716 | 89 | rows = std::max(rows, pair.second.y); | ||
1717 | 90 | } | ||
1718 | 91 | // We cound from 0 up | ||
1719 | 92 | ++columns; | ||
1720 | 93 | ++rows; | ||
1721 | 94 | |||
1722 | 76 | if (horizontal_) { | 95 | if (horizontal_) { |
1724 | 77 | unsigned int s = columns; | 96 | const int16_t s = columns; |
1725 | 78 | columns = rows; | 97 | columns = rows; |
1726 | 79 | rows = s; | 98 | rows = s; |
1727 | 80 | } | 99 | } |
1728 | 100 | return Widelands::Extent(columns, rows); | ||
1729 | 101 | } | ||
1730 | 102 | |||
1731 | 103 | void AbstractWaresDisplay::set_hgap(int32_t gap, bool relayout) { | ||
1732 | 104 | hgap_ = gap; | ||
1733 | 105 | recalc_desired_size(relayout); | ||
1734 | 106 | } | ||
1735 | 107 | |||
1736 | 108 | void AbstractWaresDisplay::set_vgap(int32_t gap, bool relayout) { | ||
1737 | 109 | vgap_ = gap; | ||
1738 | 110 | recalc_desired_size(relayout); | ||
1739 | 111 | } | ||
1740 | 112 | |||
1741 | 113 | void AbstractWaresDisplay::recalc_desired_size(bool relayout) { | ||
1742 | 114 | relayout_icons_order_coords(); | ||
1743 | 115 | |||
1744 | 116 | // Find out geometry from icons_order | ||
1745 | 117 | const Widelands::Extent size = get_extent(); | ||
1746 | 81 | 118 | ||
1747 | 82 | // 25 is height of curware_ text | 119 | // 25 is height of curware_ text |
1748 | 83 | set_desired_size( | 120 | set_desired_size( |
1751 | 84 | columns * (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X) + 1, | 121 | size.w * (kWareMenuPicWidth + hgap_) - hgap_ + 5, |
1752 | 85 | rows * (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y) + 1 + 25); | 122 | size.h * (kWareMenuPicHeight + kWareMenuInfoSize + vgap_) - vgap_ + 1 + 25); |
1753 | 123 | |||
1754 | 124 | if (relayout) { | ||
1755 | 125 | // Since we are usually stacked deep within other panels, we need to tell our highest parent window to relayout | ||
1756 | 126 | UI::Panel* p = this; | ||
1757 | 127 | while (p->get_parent()) { | ||
1758 | 128 | p = p->get_parent(); | ||
1759 | 129 | if (dynamic_cast<UI::Window*>(p)) { | ||
1760 | 130 | p->layout(); | ||
1761 | 131 | return; | ||
1762 | 132 | } | ||
1763 | 133 | } | ||
1764 | 134 | } | ||
1765 | 86 | } | 135 | } |
1766 | 87 | 136 | ||
1767 | 88 | bool AbstractWaresDisplay::handle_mousemove(uint8_t state, int32_t x, int32_t y, int32_t, int32_t) { | 137 | bool AbstractWaresDisplay::handle_mousemove(uint8_t state, int32_t x, int32_t y, int32_t, int32_t) { |
1768 | @@ -162,25 +211,56 @@ | |||
1769 | 162 | * DescriptionIndex::null() if the given point is outside the range. | 211 | * DescriptionIndex::null() if the given point is outside the range. |
1770 | 163 | */ | 212 | */ |
1771 | 164 | Widelands::DescriptionIndex AbstractWaresDisplay::ware_at_point(int32_t x, int32_t y) const { | 213 | Widelands::DescriptionIndex AbstractWaresDisplay::ware_at_point(int32_t x, int32_t y) const { |
1777 | 165 | if (x < 0 || y < 0) | 214 | // Graphical offset |
1778 | 166 | return Widelands::INVALID_INDEX; | 215 | x -= 2; |
1779 | 167 | 216 | y -= 2; | |
1780 | 168 | unsigned int i = x / (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X); | 217 | |
1781 | 169 | unsigned int j = y / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y); | 218 | if (x < 0 || y < 0) { |
1782 | 219 | return Widelands::INVALID_INDEX; | ||
1783 | 220 | } | ||
1784 | 221 | |||
1785 | 222 | int i = x / (kWareMenuPicWidth + hgap_); | ||
1786 | 223 | int j = y / (kWareMenuPicHeight + kWareMenuInfoSize + vgap_); | ||
1787 | 224 | if (kWareMenuPicWidth * (i + 1) + hgap_ * i < x || | ||
1788 | 225 | (kWareMenuPicHeight + kWareMenuInfoSize) * (j + 1) + vgap_ * j < y) { | ||
1789 | 226 | // Not on the ware, but on the space between | ||
1790 | 227 | return Widelands::INVALID_INDEX; | ||
1791 | 228 | } | ||
1792 | 170 | if (horizontal_) { | 229 | if (horizontal_) { |
1794 | 171 | unsigned int s = i; | 230 | int s = i; |
1795 | 172 | i = j; | 231 | i = j; |
1796 | 173 | j = s; | 232 | j = s; |
1797 | 174 | } | 233 | } |
1807 | 175 | if (i < icons_order().size() && j < icons_order()[i].size()) { | 234 | for (const auto& pair : icons_order_coords()) { |
1808 | 176 | const Widelands::DescriptionIndex& ware = icons_order()[i][j]; | 235 | if (pair.second.x == i && pair.second.y == j) { |
1809 | 177 | assert(hidden_.count(ware) == 1); | 236 | assert(hidden_.count(pair.first) == 1); |
1810 | 178 | if (!(hidden_.find(ware)->second)) { | 237 | if (!(hidden_.find(pair.first)->second)) { |
1811 | 179 | return ware; | 238 | return pair.first; |
1812 | 180 | } | 239 | } |
1813 | 181 | } | 240 | break; |
1814 | 182 | 241 | } | |
1815 | 183 | return Widelands::INVALID_INDEX; | 242 | } |
1816 | 243 | |||
1817 | 244 | return Widelands::INVALID_INDEX; | ||
1818 | 245 | } | ||
1819 | 246 | |||
1820 | 247 | Widelands::DescriptionIndex AbstractWaresDisplay::ware_at_coords(int16_t x, int16_t y) const { | ||
1821 | 248 | for (const auto& pair : icons_order_coords()) { | ||
1822 | 249 | if (pair.second.x == x && pair.second.y == y) { | ||
1823 | 250 | return pair.first; | ||
1824 | 251 | } | ||
1825 | 252 | } | ||
1826 | 253 | return Widelands::INVALID_INDEX; | ||
1827 | 254 | } | ||
1828 | 255 | |||
1829 | 256 | uint16_t AbstractWaresDisplay::column_length(int16_t x) const { | ||
1830 | 257 | uint16_t l = 0; | ||
1831 | 258 | for (const auto& pair : icons_order_coords()) { | ||
1832 | 259 | if (pair.second.x == x) { | ||
1833 | 260 | l = std::max(l, static_cast<uint16_t>(pair.second.y + 1)); | ||
1834 | 261 | } | ||
1835 | 262 | } | ||
1836 | 263 | return l; | ||
1837 | 184 | } | 264 | } |
1838 | 185 | 265 | ||
1839 | 186 | // Update the anchored selection. An anchor has been created by mouse | 266 | // Update the anchored selection. An anchor has been created by mouse |
1840 | @@ -199,15 +279,13 @@ | |||
1841 | 199 | Vector2i anchor_pos = ware_position(selection_anchor_); | 279 | Vector2i anchor_pos = ware_position(selection_anchor_); |
1842 | 200 | // Add an offset to make sure the anchor line and column will be | 280 | // Add an offset to make sure the anchor line and column will be |
1843 | 201 | // selected when selecting in topleft direction | 281 | // selected when selecting in topleft direction |
1846 | 202 | int32_t anchor_x = anchor_pos.x + WARE_MENU_PIC_WIDTH / 2; | 282 | int32_t anchor_x = anchor_pos.x + kWareMenuPicWidth / 2; |
1847 | 203 | int32_t anchor_y = anchor_pos.y + WARE_MENU_PIC_HEIGHT / 2; | 283 | int32_t anchor_y = anchor_pos.y + kWareMenuPicHeight / 2; |
1848 | 204 | 284 | ||
1855 | 205 | unsigned int left_ware_idx = anchor_x / (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X); | 285 | unsigned int left_ware_idx = anchor_x / (kWareMenuPicWidth + hgap_); |
1856 | 206 | unsigned int top_ware_idx = | 286 | unsigned int top_ware_idx = anchor_y / (kWareMenuPicHeight + kWareMenuInfoSize + vgap_); |
1857 | 207 | anchor_y / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y); | 287 | unsigned int right_ware_idx = x / (kWareMenuPicWidth + hgap_); |
1858 | 208 | unsigned int right_ware_idx = x / (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X); | 288 | unsigned int bottoware_idx_ = y / (kWareMenuPicHeight + kWareMenuInfoSize + vgap_); |
1853 | 209 | unsigned int bottoware_idx_ = | ||
1854 | 210 | y / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y); | ||
1859 | 211 | unsigned int tmp; | 289 | unsigned int tmp; |
1860 | 212 | 290 | ||
1861 | 213 | // Reverse col/row and anchor/endpoint if needed | 291 | // Reverse col/row and anchor/endpoint if needed |
1862 | @@ -231,10 +309,10 @@ | |||
1863 | 231 | } | 309 | } |
1864 | 232 | 310 | ||
1865 | 233 | for (unsigned int cur_ware_x = left_ware_idx; cur_ware_x <= right_ware_idx; cur_ware_x++) { | 311 | for (unsigned int cur_ware_x = left_ware_idx; cur_ware_x <= right_ware_idx; cur_ware_x++) { |
1867 | 234 | if (cur_ware_x < icons_order().size()) { | 312 | if (cur_ware_x < icons_order_coords().size()) { |
1868 | 235 | for (unsigned cur_ware_y = top_ware_idx; cur_ware_y <= bottoware_idx_; cur_ware_y++) { | 313 | for (unsigned cur_ware_y = top_ware_idx; cur_ware_y <= bottoware_idx_; cur_ware_y++) { |
1871 | 236 | if (cur_ware_y < icons_order()[cur_ware_x].size()) { | 314 | if (cur_ware_y < static_cast<unsigned>(column_length(cur_ware_x))) { |
1872 | 237 | Widelands::DescriptionIndex ware = icons_order()[cur_ware_x][cur_ware_y]; | 315 | Widelands::DescriptionIndex ware = ware_at_coords(cur_ware_x, cur_ware_y); |
1873 | 238 | if (!hidden_[ware]) { | 316 | if (!hidden_[ware]) { |
1874 | 239 | in_selection_[ware] = true; | 317 | in_selection_[ware] = true; |
1875 | 240 | } | 318 | } |
1876 | @@ -271,26 +349,44 @@ | |||
1877 | 271 | NEVER_HERE(); | 349 | NEVER_HERE(); |
1878 | 272 | } | 350 | } |
1879 | 273 | 351 | ||
1886 | 274 | const Widelands::TribeDescr::WaresOrderCoords& AbstractWaresDisplay::icons_order_coords() const { | 352 | const WaresOrderCoords& AbstractWaresDisplay::icons_order_coords() const { |
1887 | 275 | switch (type_) { | 353 | assert(!order_coords_.empty()); |
1888 | 276 | case Widelands::wwWARE: | 354 | return order_coords_; |
1889 | 277 | return tribe_.wares_order_coords(); | 355 | } |
1890 | 278 | case Widelands::wwWORKER: | 356 | |
1891 | 279 | return tribe_.workers_order_coords(); | 357 | void AbstractWaresDisplay::relayout_icons_order_coords() { |
1892 | 358 | order_coords_.clear(); | ||
1893 | 359 | const int column_number = icons_order().size(); | ||
1894 | 360 | const int column_max_size = std::max(1, (g_gr->get_yres() - min_free_vertical_space_) / | ||
1895 | 361 | (kWareMenuPicHeight + vgap_ + kWareMenuInfoSize)); | ||
1896 | 362 | |||
1897 | 363 | int16_t column_index_to_apply = 0; | ||
1898 | 364 | for (int16_t column_index = 0; column_index < column_number; ++column_index) { | ||
1899 | 365 | const std::vector<Widelands::DescriptionIndex>& column = icons_order().at(column_index); | ||
1900 | 366 | const int row_number = column.size(); | ||
1901 | 367 | int16_t row_index_to_apply = 0; | ||
1902 | 368 | for (int16_t row_index = 0; row_index < row_number; ++row_index) { | ||
1903 | 369 | order_coords_.emplace(column.at(row_index), Widelands::Coords(column_index_to_apply, row_index_to_apply)); | ||
1904 | 370 | ++row_index_to_apply; | ||
1905 | 371 | if (row_index_to_apply >= column_max_size) { | ||
1906 | 372 | row_index_to_apply = 0; | ||
1907 | 373 | ++column_index_to_apply; | ||
1908 | 374 | } | ||
1909 | 375 | } | ||
1910 | 376 | if (row_index_to_apply > 0) { | ||
1911 | 377 | ++column_index_to_apply; | ||
1912 | 378 | } | ||
1913 | 280 | } | 379 | } |
1914 | 281 | NEVER_HERE(); | ||
1915 | 282 | } | 380 | } |
1916 | 283 | 381 | ||
1917 | 284 | Vector2i AbstractWaresDisplay::ware_position(Widelands::DescriptionIndex id) const { | 382 | Vector2i AbstractWaresDisplay::ware_position(Widelands::DescriptionIndex id) const { |
1918 | 285 | Vector2i p(2, 2); | 383 | Vector2i p(2, 2); |
1919 | 286 | if (horizontal_) { | 384 | if (horizontal_) { |
1923 | 287 | p.x += icons_order_coords()[id].second * (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X); | 385 | p.x += icons_order_coords().at(id).y * (kWareMenuPicWidth + hgap_); |
1924 | 288 | p.y += icons_order_coords()[id].first * | 386 | p.y += icons_order_coords().at(id).x * (kWareMenuPicHeight + vgap_ + kWareMenuInfoSize); |
1922 | 289 | (WARE_MENU_PIC_HEIGHT + WARE_MENU_PIC_PAD_Y + WARE_MENU_INFO_SIZE); | ||
1925 | 290 | } else { | 387 | } else { |
1929 | 291 | p.x += icons_order_coords()[id].first * (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X); | 388 | p.x += icons_order_coords().at(id).x * (kWareMenuPicWidth + hgap_); |
1930 | 292 | p.y += icons_order_coords()[id].second * | 389 | p.y += icons_order_coords().at(id).y * (kWareMenuPicHeight + vgap_ + kWareMenuInfoSize); |
1928 | 293 | (WARE_MENU_PIC_HEIGHT + WARE_MENU_PIC_PAD_Y + WARE_MENU_INFO_SIZE); | ||
1931 | 294 | } | 390 | } |
1932 | 295 | return p; | 391 | return p; |
1933 | 296 | } | 392 | } |
1934 | @@ -328,15 +424,15 @@ | |||
1935 | 328 | const Image* icon = type_ == Widelands::wwWORKER ? tribe_.get_worker_descr(id)->icon() : | 424 | const Image* icon = type_ == Widelands::wwWORKER ? tribe_.get_worker_descr(id)->icon() : |
1936 | 329 | tribe_.get_ware_descr(id)->icon(); | 425 | tribe_.get_ware_descr(id)->icon(); |
1937 | 330 | 426 | ||
1939 | 331 | dst.blit(p + Vector2i((w - WARE_MENU_PIC_WIDTH) / 2, 1), icon); | 427 | dst.blit(p + Vector2i((w - kWareMenuPicWidth) / 2, 1), icon); |
1940 | 332 | 428 | ||
1942 | 333 | dst.fill_rect(Recti(p + Vector2i(0, WARE_MENU_PIC_HEIGHT), w, WARE_MENU_INFO_SIZE), | 429 | dst.fill_rect(Recti(p + Vector2i(0, kWareMenuPicHeight), w, kWareMenuInfoSize), |
1943 | 334 | info_color_for_ware(id)); | 430 | info_color_for_ware(id)); |
1944 | 335 | 431 | ||
1945 | 336 | std::shared_ptr<const UI::RenderedText> rendered_text = | 432 | std::shared_ptr<const UI::RenderedText> rendered_text = |
1946 | 337 | UI::g_fh->render(as_richtext_paragraph(info_for_ware(id), style.info_font())); | 433 | UI::g_fh->render(as_richtext_paragraph(info_for_ware(id), style.info_font())); |
1947 | 338 | rendered_text->draw(dst, Vector2i(p.x + w - rendered_text->width() - 1, | 434 | rendered_text->draw(dst, Vector2i(p.x + w - rendered_text->width() - 1, |
1949 | 339 | p.y + WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + 1 - | 435 | p.y + kWareMenuPicHeight + kWareMenuInfoSize + 1 - |
1950 | 340 | rendered_text->height())); | 436 | rendered_text->height())); |
1951 | 341 | } | 437 | } |
1952 | 342 | 438 | ||
1953 | @@ -370,6 +466,10 @@ | |||
1954 | 370 | hidden_[ware] = true; | 466 | hidden_[ware] = true; |
1955 | 371 | } | 467 | } |
1956 | 372 | 468 | ||
1957 | 469 | bool AbstractWaresDisplay::is_ware_hidden(Widelands::DescriptionIndex ware) const { | ||
1958 | 470 | return hidden_.at(ware); | ||
1959 | 471 | } | ||
1960 | 472 | |||
1961 | 373 | WaresDisplay::WaresDisplay(UI::Panel* const parent, | 473 | WaresDisplay::WaresDisplay(UI::Panel* const parent, |
1962 | 374 | int32_t x, | 474 | int32_t x, |
1963 | 375 | int32_t y, | 475 | int32_t y, |
1964 | 376 | 476 | ||
1965 | === modified file 'src/wui/waresdisplay.h' | |||
1966 | --- src/wui/waresdisplay.h 2019-02-23 11:00:49 +0000 | |||
1967 | +++ src/wui/waresdisplay.h 2019-05-29 06:43:44 +0000 | |||
1968 | @@ -20,6 +20,7 @@ | |||
1969 | 20 | #ifndef WL_WUI_WARESDISPLAY_H | 20 | #ifndef WL_WUI_WARESDISPLAY_H |
1970 | 21 | #define WL_WUI_WARESDISPLAY_H | 21 | #define WL_WUI_WARESDISPLAY_H |
1971 | 22 | 22 | ||
1972 | 23 | #include <memory> | ||
1973 | 23 | #include <vector> | 24 | #include <vector> |
1974 | 24 | 25 | ||
1975 | 25 | #include "logic/map_objects/tribes/tribe_descr.h" | 26 | #include "logic/map_objects/tribes/tribe_descr.h" |
1976 | @@ -36,6 +37,8 @@ | |||
1977 | 36 | struct WareList; | 37 | struct WareList; |
1978 | 37 | } // namespace Widelands | 38 | } // namespace Widelands |
1979 | 38 | 39 | ||
1980 | 40 | using WaresOrderCoords = std::map<Widelands::DescriptionIndex, Widelands::Coords>; | ||
1981 | 41 | |||
1982 | 39 | /** | 42 | /** |
1983 | 40 | * Display wares or workers together with some string (typically a number) | 43 | * Display wares or workers together with some string (typically a number) |
1984 | 41 | * in the style of the @ref WarehouseWindow. | 44 | * in the style of the @ref WarehouseWindow. |
1985 | @@ -54,7 +57,9 @@ | |||
1986 | 54 | CLANG_DIAG_OFF("-Wunknown-pragmas") CLANG_DIAG_OFF("-Wzero-as-null-pointer-constant") | 57 | CLANG_DIAG_OFF("-Wunknown-pragmas") CLANG_DIAG_OFF("-Wzero-as-null-pointer-constant") |
1987 | 55 | boost::function<void(Widelands::DescriptionIndex, bool)> callback_function = 0, | 58 | boost::function<void(Widelands::DescriptionIndex, bool)> callback_function = 0, |
1988 | 56 | CLANG_DIAG_ON("-Wzero-as-null-pointer-constant") | 59 | CLANG_DIAG_ON("-Wzero-as-null-pointer-constant") |
1990 | 57 | CLANG_DIAG_ON("-Wunknown-pragmas") bool horizontal = false); | 60 | CLANG_DIAG_ON("-Wunknown-pragmas") bool horizontal = false, |
1991 | 61 | int32_t hgap = 3, | ||
1992 | 62 | int32_t vgap = 4); | ||
1993 | 58 | 63 | ||
1994 | 59 | bool | 64 | bool |
1995 | 60 | handle_mousemove(uint8_t state, int32_t x, int32_t y, int32_t xdiff, int32_t ydiff) override; | 65 | handle_mousemove(uint8_t state, int32_t x, int32_t y, int32_t xdiff, int32_t ydiff) override; |
1996 | @@ -68,12 +73,39 @@ | |||
1997 | 68 | 73 | ||
1998 | 69 | // Wares may be hidden | 74 | // Wares may be hidden |
1999 | 70 | void hide_ware(Widelands::DescriptionIndex); | 75 | void hide_ware(Widelands::DescriptionIndex); |
2000 | 76 | bool is_ware_hidden(Widelands::DescriptionIndex) const; | ||
2001 | 71 | 77 | ||
2002 | 72 | Widelands::DescriptionIndex ware_at_point(int32_t x, int32_t y) const; | 78 | Widelands::DescriptionIndex ware_at_point(int32_t x, int32_t y) const; |
2003 | 73 | Widelands::WareWorker get_type() const { | 79 | Widelands::WareWorker get_type() const { |
2004 | 74 | return type_; | 80 | return type_; |
2005 | 75 | } | 81 | } |
2006 | 76 | 82 | ||
2007 | 83 | int32_t get_hgap() { | ||
2008 | 84 | return hgap_; | ||
2009 | 85 | } | ||
2010 | 86 | int32_t get_vgap() { | ||
2011 | 87 | return vgap_; | ||
2012 | 88 | } | ||
2013 | 89 | void set_hgap(int32_t, bool = true); | ||
2014 | 90 | void set_vgap(int32_t, bool = true); | ||
2015 | 91 | |||
2016 | 92 | Widelands::Extent get_extent() const; | ||
2017 | 93 | |||
2018 | 94 | const WaresOrderCoords& icons_order_coords() const; | ||
2019 | 95 | Widelands::DescriptionIndex ware_at_coords(int16_t x, int16_t y) const; | ||
2020 | 96 | uint16_t column_length(int16_t) const; | ||
2021 | 97 | |||
2022 | 98 | void set_min_free_vertical_space(int32_t s) { | ||
2023 | 99 | min_free_vertical_space_ = s; | ||
2024 | 100 | } | ||
2025 | 101 | int32_t get_min_free_vertical_space() const { | ||
2026 | 102 | return min_free_vertical_space_; | ||
2027 | 103 | } | ||
2028 | 104 | |||
2029 | 105 | static inline int32_t calc_hgap(int32_t columns, int32_t total_w, int32_t min = 3) { | ||
2030 | 106 | return std::max(min, (total_w - columns * kWareMenuPicWidth) / (columns - 1)); | ||
2031 | 107 | } | ||
2032 | 108 | |||
2033 | 77 | protected: | 109 | protected: |
2034 | 78 | void layout() override; | 110 | void layout() override; |
2035 | 79 | 111 | ||
2036 | @@ -82,7 +114,6 @@ | |||
2037 | 82 | virtual RGBColor info_color_for_ware(Widelands::DescriptionIndex); | 114 | virtual RGBColor info_color_for_ware(Widelands::DescriptionIndex); |
2038 | 83 | 115 | ||
2039 | 84 | const Widelands::TribeDescr::WaresOrder& icons_order() const; | 116 | const Widelands::TribeDescr::WaresOrder& icons_order() const; |
2040 | 85 | const Widelands::TribeDescr::WaresOrderCoords& icons_order_coords() const; | ||
2041 | 86 | virtual Vector2i ware_position(Widelands::DescriptionIndex) const; | 117 | virtual Vector2i ware_position(Widelands::DescriptionIndex) const; |
2042 | 87 | void draw(RenderTarget&) override; | 118 | void draw(RenderTarget&) override; |
2043 | 88 | virtual void draw_ware(RenderTarget&, Widelands::DescriptionIndex); | 119 | virtual void draw_ware(RenderTarget&, Widelands::DescriptionIndex); |
2044 | @@ -110,6 +141,13 @@ | |||
2045 | 110 | WareListSelectionType in_selection_; // Wares in temporary anchored selection | 141 | WareListSelectionType in_selection_; // Wares in temporary anchored selection |
2046 | 111 | bool selectable_; | 142 | bool selectable_; |
2047 | 112 | bool horizontal_; | 143 | bool horizontal_; |
2048 | 144 | int32_t hgap_; | ||
2049 | 145 | int32_t vgap_; | ||
2050 | 146 | |||
2051 | 147 | WaresOrderCoords order_coords_; | ||
2052 | 148 | |||
2053 | 149 | void relayout_icons_order_coords(); | ||
2054 | 150 | void recalc_desired_size(bool); | ||
2055 | 113 | 151 | ||
2056 | 114 | /** | 152 | /** |
2057 | 115 | * The ware on which the mouse press has been performed. | 153 | * The ware on which the mouse press has been performed. |
2058 | @@ -117,6 +155,9 @@ | |||
2059 | 117 | */ | 155 | */ |
2060 | 118 | Widelands::DescriptionIndex selection_anchor_; | 156 | Widelands::DescriptionIndex selection_anchor_; |
2061 | 119 | boost::function<void(Widelands::DescriptionIndex, bool)> callback_function_; | 157 | boost::function<void(Widelands::DescriptionIndex, bool)> callback_function_; |
2062 | 158 | |||
2063 | 159 | std::unique_ptr<Notifications::Subscriber<GraphicResolutionChanged>> graphic_resolution_changed_subscriber_; | ||
2064 | 160 | int32_t min_free_vertical_space_; | ||
2065 | 120 | }; | 161 | }; |
2066 | 121 | 162 | ||
2067 | 122 | /* | 163 | /* |
Continuous integration builds have changed state:
Travis build 4886. State: failed. Details: https:/ /travis- ci.org/ widelands/ widelands/ builds/ 528245915. /ci.appveyor. com/project/ widelands- dev/widelands/ build/_ widelands_ dev_widelands_ economy_ target_ profiles- 4667.
Appveyor build 4667. State: success. Details: https:/