Issues (229)

client/osci/dialog/ConstructionDlg.py (1 issue)

Severity
1
#
2
#  Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/]
3
#
4
#  This file is part of Outer Space.
5
#
6
#  Outer Space is free software; you can redistribute it and/or modify
7
#  it under the terms of the GNU General Public License as published by
8
#  the Free Software Foundation; either version 2 of the License, or
9
#  (at your option) any later version.
10
#
11
#  Outer Space is distributed in the hope that it will be useful,
12
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
#  GNU General Public License for more details.
15
#
16
#  You should have received a copy of the GNU General Public License
17
#  along with Outer Space; if not, write to the Free Software
18
#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
#
20
21
import pygame
22
23
import pygameui as ui
24
25
from ige import GameException
26
from ige.ospace import ShipUtils, Rules
27
import ige.ospace.Const as Const
28
29
from osci import gdata, res, client, sequip
30
from osci.StarMapWidget import StarMapWidget
31
32
from ConstrSelTechDlg import ConstrSelTechDlg
33
from ConstrUpgradeDlg import ConstrUpgradeDlg
34
from ConfirmDlg import ConfirmDlg
35
36
class ConstructionDlg:
37
38
    def __init__(self, app):
39
        self.app = app
40
        self.createUI()
41
        self.selTechDlg = ConstrSelTechDlg(app)
42
        self.upgradeDlg = ConstrUpgradeDlg(app)
43
        self.confirmDlg = ConfirmDlg(app)
44
        self.selectedDesignID = None
45
        self.highlightedDesignID = None
46
        self.editMode = False
47
48
    def display(self):
49
        self.itemCache = {}
50
        self.hullID = Const.OID_NONE
51
        self.ctrlID = Const.OID_NONE
52
        self.eqIDs = {}
53
        self.selectedEqID = None
54
        self.update()
55
        self.win.show()
56
        # register for updates
57
        if self not in gdata.updateDlgs:
58
            gdata.updateDlgs.append(self)
59
60
    def hide(self):
61
        self.win.setStatus(_("Ready."))
62
        self.win.hide()
63
        # unregister updates
64
        if self in gdata.updateDlgs:
65
            gdata.updateDlgs.remove(self)
66
67
    def update(self):
68
        self.showDesigns()
69
        self.showDetails()
70
71
    def _getNumberInFleets(self, designID):
72
        count = 0
73
        for fleetID in client.getPlayer().fleets:
74
            fleet = client.get(fleetID)
75
            count += len([designID for tmpDesignID, hp, shieldHP, exp in fleet.ships if tmpDesignID == designID])
76
        return count
77
78
    def _getNumberInBuild(self, designID):
79
        count = 0
80
        # planet queues
81
        for planetID in client.db.keys():
82
            planet = client.get(planetID, noUpdate=1)
83
            # skip non-planets
84
            try:
85
                count += sum((task.quantity for task in planet.prodQueue if (task.isShip and task.techID == designID)))
86
            except AttributeError:
87
                # this is either not a planet, or it's not planet with prodqueue useful for us
88
                continue
89
        # global queues
90
        for globalQueue in client.getPlayer().prodQueues:
91
            count += sum((task.quantity for task in globalQueue if (task.isShip and task.techID == designID)))
92
        return count
93
94
    def showDesigns(self):
95
        player = client.getPlayer()
96
        # check if highlighted ship design exists
97
        if self.highlightedDesignID not in player.shipDesigns:
98
            self.highlightedDesignID = None
99
        # designs
100
        highlighted = None
101
        items = []
102
        for designID in player.shipDesigns:
103
            spec = player.shipDesigns[designID]
104
105
            countInService = self._getNumberInFleets(designID)
106
            countInBuild = self._getNumberInBuild(designID)
107
108
            # ui list item
109
            hullTech = client.getFullTechInfo(spec.hullID)
110
            item = ui.Item(spec.name, tDesignID=designID,
111
                           tClass="%s/%s%d" % (_(gdata.shipClasses[spec.combatClass][:1].upper()),
112
                                               _("TL"),
113
                                               hullTech.level),
114
                           tNumber=countInService,
115
                           tInBuild=countInBuild)
116
            if spec.upgradeTo:
117
                item.foreground = gdata.sevColors[gdata.NONE]
118
            if designID == self.highlightedDesignID:
119
                highlighted = item
120
            items.append(item)
121
        self.win.vDesigns.items = items
122
        self.win.vDesigns.itemsChanged()
123
        self.win.vDesigns.highlightItem(highlighted, 0)
124
125
    def _setDetailButtons(self, player):
126
        if self.selectedDesignID:
127
            self.win.vScrap.enabled = 1
128
            if player.shipDesigns[self.selectedDesignID].upgradeTo == 0:
129
                self.win.vUpgrade.enabled = 1
130
                self.win.vUpgrade.text = _("Upgrade")
131
            else:
132
                self.win.vUpgrade.enabled = 1
133
                self.win.vUpgrade.text = _("Cancel Upgrd")
134
135
        if self.editMode:
136
            self.win.vName.enabled = 1
137
            self.win.vEnginesButton.enabled = 1
138
            self.win.vWeaponsButton.enabled = 1
139
            self.win.vEquipmentButton.enabled = 1
140
            self.win.vUpgrade.enabled = 0
141
            self.win.vUpgrade.text = _("Upgrade")
142
            self.win.vScrap.enabled = 0
143
        else:
144
            # view only mode?
145
            # let's reset highlights in design listboxes
146
            self.selectedEqID = None
147
            self.win.vName.enabled = 0
148
            self.win.vEngines.unselectAll()
149
            self.win.vWeapons.unselectAll()
150
            self.win.vEquipment.unselectAll()
151
152
            self.win.vDuplDesign.enabled = 1
153
            self.win.vConstruct.enabled = 0
154
            self.win.vEnginesButton.enabled = 0
155
            self.win.vWeaponsButton.enabled = 0
156
            self.win.vEquipmentButton.enabled = 0
157
            if not self.selectedDesignID:
158
                self.win.vScrap.enabled = 0
159
                self.win.vUpgrade.enabled = 0
160
161
    def _designRepresentation(self, player):
162
        if self.highlightedDesignID is None:
163
            if self.editMode:
164
                if self.ctrlID:
165
                    eqIDs = {self.ctrlID: 1}
166
                else:
167
                    eqIDs = {}
168
                for eqID in self.eqIDs:
169
                    eqIDs[eqID] = self.eqIDs[eqID]
170
                improvements = []
171
            else:
172
                self.hullID = self.ctrlID = None
173
                self.win.vName.text = ""
174
                self.eqIDs = {}
175
                eqIDs = {}
176
                improvements = []
177
        else:
178
            spec = player.shipDesigns[self.highlightedDesignID]
179
            self.hullID = spec.hullID
180
            eqIDs = spec.eqIDs
181
            improvements = spec.improvements
182
            self.win.vName.text = spec.name
183
            self.win.vHull.text = client.getTechInfo(self.hullID).name
184
            self.eqIDs = {}
185
            for eqID in eqIDs:
186
                tech = client.getTechInfo(eqID)
187
                if tech.subtype == "seq_ctrl":
188
                    self.ctrlID = eqID
189
                    self.win.vCtrl.text = tech.name
190
                else:
191
                    self.eqIDs[eqID] = eqIDs[eqID]
192
        try:
193
            result = ShipUtils.makeShipFullSpec(player, None, self.hullID, eqIDs, improvements)
194
            if self.editMode:
195
                self.win.vConstruct.enabled = 1
196
        except GameException, e:
197
            self.win.setStatus(e.args[0])
198
            self.win.vConstruct.enabled = 0
199
            try:
200
                result = ShipUtils.makeShipFullSpec(player, None, self.hullID, eqIDs,
201
                                                    improvements, raiseExs=False)
202
            except GameException:
203
                result = None
204
        else:
205
            self.win.setStatus(_("Ready."))
206
        return result
207
208
    def _detailEquipmentLists(self):
209
        # design info
210
        if self.hullID:
211
            tech = client.getTechInfo(self.hullID)
212
            self.win.vHull.text = tech.name  # TODO _(tech.name)
213
        elif self.editMode:
214
            self.win.vHull.text = _("[Click to select]")
215
        else:
216
            self.win.vHull.text = ""
217
        if self.ctrlID:
218
            tech = client.getTechInfo(self.ctrlID)
219
            self.win.vCtrl.text = tech.name  # TODO _(tech.name)
220
        elif self.editMode:
221
            self.win.vCtrl.text = _("[Click to select]")
222
        else:
223
            self.win.vCtrl.text = ""
224
        # equipments
225
        engines = []
226
        weapons = []
227
        equipment = []
228
        selected = None
229
        selected_type = None
230
        for eqID in self.eqIDs:
231
            tech = client.getTechInfo(eqID)
232
            short = sequip.getShortDescr(eqID)
233
            _long = sequip.getLongDescr(eqID)
234
            # cache has been introduced to let items preserve highlight information
235
            if eqID in self.itemCache:
236
                item = self.itemCache[eqID]
237
                item.tNumber = self.eqIDs[eqID]
238
            else:
239
                item = ui.Item(tech.name,
240
                               techID=eqID,
241
                               tNumber=self.eqIDs[eqID],
242
                               tData=short,
243
                               tooltipTitle=_("Details"),
244
                               tooltip=_long,
245
                               statustip=_long)
246
                self.itemCache[eqID] = item
247
            if eqID == self.selectedEqID:
248
                selected = item
249
                selected_type = tech.subtype
250
            if tech.subtype == "seq_eng":
251
                engines.append(item)
252
            elif tech.subtype == "seq_wpn":
253
                weapons.append(item)
254
            elif tech.subtype in ["seq_mod", "seq_struct"]:
255
                equipment.append(item)
256
        self.win.vEngines.items = engines
257
        self.win.vEngines.itemsChanged()
258
        if selected_type == "seq_eng":
259
            self.win.vEngines.selectItem(selected)
260
        else:
261
            self.win.vEngines.selectItem(None)
262
        self.win.vWeapons.items = weapons
263
        self.win.vWeapons.itemsChanged()
264
        if selected_type == "seq_wpn":
265
            self.win.vWeapons.selectItem(selected)
266
        else:
267
            self.win.vWeapons.selectItem(None)
268
        self.win.vEquipment.items = equipment
269
        self.win.vEquipment.itemsChanged()
270
        if selected_type == "seq_mod":
271
            self.win.vEquipment.selectItem(selected)
272
        else:
273
            self.win.vEquipment.selectItem(None)
274
275
    def _detailComputedAttributes(self, player, result):
276
        if result:
277
            hull = client.getTechInfo(result.hullID)
278
            self.win.vAClass.text = _(gdata.shipClasses[result.combatClass])
279
            self.win.vASignature.text = _("%d") % result.signature
280
            if result.speed == result.battleSpeed:
281
                self.win.vSpeed.text = _("Speed")
282
                self.win.vASpeed.text = _("%.2f") % result.speed
283
            else:
284
                self.win.vSpeed.text = _("Spd FTL (STL)")
285
                self.win.vASpeed.text = _("%.2f (%.2f)") % (result.speed, result.battleSpeed)
286
            self.win.vAHP.text = _("%d - %d") % (result.maxHP, result.shieldHP) if result.shieldHP > 0 else _("%d") % result.maxHP
287
            self.win.vAAttack.text = _("%d") % result.combatAtt
288
            self.win.vADefence.text = _("%d / %d") % (result.combatDef, result.missileDef)
289
            self.win.vAPayload.text = _("%d") % (hull.maxWeight - result.weight) if getattr(hull, "maxWeight", None) else _("N/A")
290
            self.win.vASlots.text = _("%d") % (hull.slots - result.slots) if hasattr(hull, "slots") else _("N/A")
291
            self.win.vATanks.text = _("%d") % result.storEn
292
            if result.speed > 0 and result.operEn > 0:
293
                support = result.storEn / result.operEn
294
                self.win.vARange.text = _("%.2f") % (support * result.speed / Rules.turnsPerDay)
295
            else:
296
                self.win.vARange.text = _("None")
297
            self.win.vACCPts.text = _("%d") % result.buildProd
298
            self.win.vACombatPwr.text = _("%d") % result.combatPwr
299
            if self.highlightedDesignID and player.shipDesigns[self.highlightedDesignID].upgradeTo:
300
                self.win.vAUpgrade.text = player.shipDesigns[player.shipDesigns[self.highlightedDesignID].upgradeTo].name
301
                self.win.vAUpgrade.font = "normal-italic"
302
            else:
303
                self.win.vAUpgrade.text = _("N/A")
304
                self.win.vAUpgrade.font = "normal"
305
        else:
306
            self.win.vAClass.text = _("N/A")
307
            self.win.vASignature.text = _("N/A")
308
            self.win.vASpeed.text = _("N/A")
309
            self.win.vAHP.text = _("N/A")
310
            self.win.vAAttack.text = _("N/A")
311
            self.win.vADefence.text = _("N/A")
312
            self.win.vAPayload.text = _("N/A")
313
            self.win.vASlots.text = _("N/A")
314
            self.win.vATanks.text = _("N/A")
315
            self.win.vARange.text = _("N/A")
316
            self.win.vACCPts.text = _("N/A")
317
            self.win.vACombatPwr.text = _("N/A")
318
            self.win.vAUpgrade.text = _("N/A")
319
320
    def showDetails(self):
321
        player = client.getPlayer()
322
        self._setDetailButtons(player)
323
        result = self._designRepresentation(player)
324
        self._detailEquipmentLists()
325
        self._detailComputedAttributes(player, result)
326
327
    def onConstruct(self, widget, action, data):
328
        name = self.win.vName.text
329
        if not name:
330
            self.win.setStatus(_("Enter name of the design."))
331
            return
332
        # compute
333
        player = client.getPlayer()
334
        if self.ctrlID:
335
            eqIDs = {self.ctrlID: 1}
336
        else:
337
            eqIDs = {}
338
        for eqID in self.eqIDs:
339
            if self.eqIDs[eqID]:
340
                eqIDs[eqID] = self.eqIDs[eqID]
341
        try:
342
            self.win.setStatus(_("Executing ADD SHIP DESIGN command..."))
343
            player = client.getPlayer()
344
            player.shipDesigns, self.selectedDesignID = \
345
                client.cmdProxy.addShipDesign(player.oid, name, self.hullID, eqIDs)
346
            self.win.vDuplDesign.enabled = 1
347
            self.win.setStatus(_('Command has been executed.'))
348
        except GameException, e:
349
            self.win.setStatus(_(e.args[0]))
350
            return
351
        self.editMode = False
352
        self.update()
353
354
    def onClose(self, widget, action, data):
355
        self.editMode = False
356
        self.hide()
357
358
    def onSelectHull(self, widget, action, data):
359
        if self.editMode:
360
            self.selTechDlg.display('isShipHull', [], self.onHullSelected, self.hullID, self.hullID)
361
362
    def onHullSelected(self, hullID):
363
        self.hullID = hullID
364
        self.showDetails()
365
366
    def onSelectCtrl(self, widget, action, data):
367
        if self.editMode:
368
            self.selTechDlg.display('isShipEquip', ["seq_ctrl"], self.onCtrlSelected, self.ctrlID, self.hullID)
369
370
    def onCtrlSelected(self, ctrlID):
371
        self.ctrlID = ctrlID
372
        self.showDetails()
373
374
    def onAddEngine(self, widget, action, data):
375
        self.selTechDlg.display('isShipEquip', ["seq_eng"], self.onEqSelected, hullID=self.hullID)
376
377
    def onAddWeapon(self, widget, action, data):
378
        self.selTechDlg.display('isShipEquip', ["seq_wpn"], self.onEqSelected, hullID=self.hullID)
379
380
    def onAddEquipment(self, widget, action, data):
381
        self.selTechDlg.display('isShipEquip', ["seq_mod", "seq_struct"], self.onEqSelected, hullID=self.hullID)
382
383
    def onEqSelected(self, eqID):
384
        self.eqIDs[eqID] = self.eqIDs.get(eqID, 0) + 1
385
        self.showDetails()
386
387
    def onSelectDesign(self, widget, action, data):
388
        item = self.win.vDesigns.selection[0]
389
        self.editMode = False
390
        self.selectedDesignID = self.highlightedDesignID = item.tDesignID
391
        self.showDetails()
392
393
    def onHighlightDesign(self, widget, action, data):
394
        if self.editMode:
395
            return
396
        if data is None and not self.win.vDesigns.selection:
397
            # unhighlight into non-selection
398
            self.highlightedDesignID = None
399
            self.win.vDuplDesign.enabled = 0
400
            self.showDetails()
401
            return
402
        if data is not None:
403
            item = self.win.vDesigns.highlight
404
        elif self.win.vDesigns.selection:
405
            item = self.win.vDesigns.selection[0]
406
        self.highlightedDesignID = item.tDesignID
0 ignored issues
show
The variable item does not seem to be defined for all execution paths.
Loading history...
407
        self.showDetails()
408
409
    def onNewDesign(self, widget, action, data):
410
        self.selectedDesignID = self.highlightedDesignID = None
411
        self.editMode = True
412
        self.win.vDesigns.selectItem(None)
413
        self.hullID = Const.OID_NONE
414
        self.ctrlID = Const.OID_NONE
415
        self.eqIDs = {}
416
        self.win.vName.text = _(" ")
417
        self.win.vDuplDesign.enabled = 0
418
        self.update()
419
420
    def onDuplDesign(self, widget, action, data):
421
        self.selectedDesignID = None
422
        self.highlightedDesignID = None
423
        self.editMode = True
424
        self.win.vDesigns.selectItem(None)
425
        self.win.vName.text = _(" ")
426
        self.win.vDuplDesign.enabled = 0
427
        self.update()
428
429
    def _getSelectedWidget(self):
430
        widgets = []
431
        if self.win.vEngines.selection:
432
            widgets.append(self.win.vEngines)
433
        if self.win.vWeapons.selection:
434
            widgets.append(self.win.vWeapons)
435
        if self.win.vEquipment.selection:
436
            widgets.append(self.win.vEquipment)
437
        return widgets
438
439
    def onEqSelectedInListInc(self, widget, action, data):
440
        if self.editMode:
441
            self._onEqSelectedInList(widget)
442
            if not pygame.key.get_mods() & pygame.KMOD_SHIFT:
443
                self._onChangeEquipmentQty(1)
444
            else:
445
                self._onChangeEquipmentQty(5)
446
447
    def onEqSelectedInListDec(self, widget, action, data):
448
        if self.editMode:
449
            self._onEqSelectedInList(widget)
450
            if not pygame.key.get_mods() & pygame.KMOD_SHIFT:
451
                self._onChangeEquipmentQty(-1)
452
            else:
453
                self._onChangeEquipmentQty(-5)
454
455
    def _onEqSelectedInList(self, widget):
456
        for old_select_widget in self._getSelectedWidget():
457
            if old_select_widget is not widget:
458
                old_select_widget.unselectAll()
459
        self.selectedEqID = widget.selection[0].techID
460
461
    def _onChangeEquipmentQty(self, delta):
462
        for widget in self._getSelectedWidget():
463
            item = widget.selection[0]
464
            eqID = item.techID
465
            self.eqIDs[eqID] = max(self.eqIDs.get(eqID, 0) + delta, 0)
466
            self.showDetails()
467
468
    def onRemoveEquipment(self, widget, action, data):
469
        if self.win.vEquipment.selection:
470
            item = self.win.vEquipment.selection[0]
471
            eqID = item.techID
472
            del self.eqIDs[eqID]
473
            self.showDetails()
474
475
    def onScrap(self, widget, action, data):
476
        # count number of ships using this design
477
        count = 0
478
        for fleetID in client.getPlayer().fleets:
479
            fleet = client.get(fleetID)
480
            for designID, hp, shieldHP, exp in fleet.ships:
481
                if designID == self.selectedDesignID:
482
                    count += 1
483
        self.confirmDlg.display(_('Deletion of this design dismantle %d ship(s). Are you sure to scrap it?') % count,
484
                                _('Yes'),
485
                                _('No'),
486
                                confirmAction=self.onScrapConfirmed,
487
                                agreementNeeded=count != 0)
488
489
    def onScrapConfirmed(self):
490
        self.win.vDuplDesign.enabled = 0
491
        try:
492
            self.win.setStatus(_("Executing SCRAP SHIP DESIGN command..."))
493
            player = client.getPlayer()
494
            oldFleets = player.fleets
495
            player.shipDesigns, player.fleets, player.stratRes, player.prodQueues = \
496
                client.cmdProxy.scrapShipDesign(player.oid, self.selectedDesignID)
497
            self.selectedDesignID = None
498
            self.win.setStatus(_('Command has been executed.'))
499
        except GameException, e:
500
            self.win.setStatus(_(e.args[0]))
501
            return
502
        # reread information about fleets and planets
503
        oldFleets.extend(player.planets)
504
        client.updateIDs(oldFleets)
505
506
        gdata.mainGameDlg.update()
507
        self.update()
508
509
    def onUpgrade(self, widget, action, data):
510
        player = client.getPlayer()
511
        if player.shipDesigns[self.selectedDesignID].upgradeTo == 0:
512
            # upgrade
513
            self.upgradeDlg.display(self.selectedDesignID, self)
514
        else:
515
            # cancel upgrade
516
            try:
517
                self.win.setStatus(_("Executing CANCEL UPGRADE SHIP DESIGN command..."))
518
                player.shipDesigns = \
519
                    client.cmdProxy.cancelUpgradeShipDesign(player.oid, self.selectedDesignID)
520
                self.win.setStatus(_('Command has been executed.'))
521
            except GameException, e:
522
                self.win.setStatus(_(e.args[0]))
523
                return
524
            self.update()
525
526
    def createUI(self):
527
        w, h = gdata.scrnSize
528
        self.win = ui.Window(self.app,
529
                             modal=1,
530
                             escKeyClose=1,
531
                             titleOnly=w == 800 and h == 600,
532
                             movable=0,
533
                             title=_('Construction Centre'),
534
                             rect=ui.Rect((w - 800 - 4 * (w != 800)) / 2,
535
                                          (h - 600 - 4 * (h != 600)) / 2,
536
                                          800 + 4 * (w != 800),
537
                                          580 + 4 * (h != 600)),
538
                             layoutManager=ui.SimpleGridLM())
539
        self.win.subscribeAction('*', self)
540
        # player listing
541
        ui.Title(self.win, layout=(0, 0, 15, 1), text=_('Ship Designs'),
542
                 font='normal-bold', align=ui.ALIGN_W)
543
        ui.Listbox(self.win, layout=(0, 1, 15, 25), id='vDesigns',
544
                   columns=((_('#'), 'tNumber', 2, ui.ALIGN_E),
545
                            (_('B'), 'tInBuild', 2, ui.ALIGN_E),
546
                            (_('Name'), 'text', 8, ui.ALIGN_W),
547
                            (_('Class'), 'tClass', 2, ui.ALIGN_W)),
548
                   columnLabels=1,
549
                   action="onSelectDesign",
550
                   hoverAction="onHighlightDesign")
551
        ui.Button(self.win, layout=(0, 26, 7, 1), text=_("New design"),
552
                  action="onNewDesign")
553
        ui.Button(self.win, layout=(7, 26, 7, 1), text=_("Dupl. design"),
554
                  action="onDuplDesign", enabled=0, id="vDuplDesign")
555
        # current design
556
        ui.Title(self.win, layout=(15, 0, 25, 1), text=_('Design'),
557
                 font='normal-bold', align=ui.ALIGN_W)
558
        # info
559
        ui.Label(self.win, layout=(15, 1, 5, 1), text=_("Name"),
560
                 align=ui.ALIGN_W)
561
        ui.Entry(self.win, layout=(20, 1, 10, 1), id="vName",
562
                 align=ui.ALIGN_E)
563
        ui.Label(self.win, layout=(15, 2, 5, 1), text=_("Hull type"),
564
                 align=ui.ALIGN_W)
565
        ui.ActiveLabel(self.win, layout=(20, 2, 10, 1), id="vHull",
566
                       align=ui.ALIGN_E, action="onSelectHull")
567
        ui.Label(self.win, layout=(15, 3, 5, 1), text=_("Control unit"),
568
                 align=ui.ALIGN_W)
569
        ui.ActiveLabel(self.win, layout=(20, 3, 10, 1), id="vCtrl",
570
                       align=ui.ALIGN_E, action="onSelectCtrl")
571
        ui.Button(self.win, layout=(15, 4, 6, 1), text=_('Engines'),
572
                  id="vEnginesButton", font='normal-bold', action="onAddEngine")
573
        ui.Title(self.win, layout=(21, 4, 19, 1),)
574
        ui.Listbox(self.win, layout=(15, 5, 25, 3), id='vEngines',
575
                   columns=((_('#'), 'tNumber', 2, ui.ALIGN_E),
576
                            (_('Name'), 'text', 8, ui.ALIGN_W),
577
                            (_('Data'), 'tData', 14, ui.ALIGN_W)),
578
                   columnLabels=0,
579
                   action="onEqSelectedInListInc",
580
                   rmbAction="onEqSelectedInListDec")
581
        ui.Button(self.win, layout=(15, 8, 6, 1), text=_('Weapons'),
582
                  id="vWeaponsButton", font='normal-bold', action="onAddWeapon")
583
        ui.Title(self.win, layout=(21, 8, 19, 1),)
584
        ui.Listbox(self.win, layout=(15, 9, 25, 4), id='vWeapons',
585
                   columns=((_('#'), 'tNumber', 2, ui.ALIGN_E),
586
                            (_('Name'), 'text', 8, ui.ALIGN_W),
587
                            (_('Data'), 'tData', 14, ui.ALIGN_W)),
588
                   columnLabels=0,
589
                   action="onEqSelectedInListInc",
590
                   rmbAction="onEqSelectedInListDec")
591
        ui.Button(self.win, layout=(15, 13, 6, 1), text=_('Equipment'),
592
                  id="vEquipmentButton", font='normal-bold', action="onAddEquipment")
593
        ui.Title(self.win, layout=(21, 13, 19, 1),)
594
        ui.Listbox(self.win, layout=(15, 14, 25, 5), id='vEquipment',
595
                   columns=((_('#'), 'tNumber', 2, ui.ALIGN_E),
596
                            (_('Name'), 'text', 8, ui.ALIGN_W),
597
                            (_('Data'), 'tData', 14, ui.ALIGN_W)),
598
                   columnLabels=0,
599
                   action="onEqSelectedInListInc",
600
                   rmbAction="onEqSelectedInListDec")
601
602
        ui.Button(self.win, layout=(15, 19, 6, 1), text=_("Upgrade to"),
603
                  id="vUpgrade", font='normal-bold', action="onUpgrade")
604
        ui.Label(self.win, layout=(21, 19, 6, 1), id="vAUpgrade", align=ui.ALIGN_E)
605
        ui.Title(self.win, layout=(27.5, 19, 12.5, 1))
606
607
        # ship's attrs
608
        ui.Label(self.win, layout=(30.5, 1, 4.5, 1), text=_("Class"), align=ui.ALIGN_W)
609
        ui.Label(self.win, layout=(35, 1, 4.75, 1), id="vAClass", align=ui.ALIGN_E)
610
        ui.Label(self.win, layout=(30.5, 2, 6.5, 1), text=_("Free slots"), align=ui.ALIGN_W)
611
        ui.Label(self.win, layout=(37, 2, 2.75, 1), id="vASlots", align=ui.ALIGN_E)
612
        ui.Label(self.win, layout=(30.5, 3, 6.5, 1), text=_("Unused payload"), align=ui.ALIGN_W)
613
        ui.Label(self.win, layout=(37, 3, 2.75, 1), id="vAPayload", align=ui.ALIGN_E)
614
615
        ui.Label(self.win, layout=(17, 21, 4, 1), text=_("HP"), align=ui.ALIGN_W)
616
        ui.Label(self.win, layout=(21, 21, 5, 1), id="vAHP", align=ui.ALIGN_E)
617
        ui.Label(self.win, layout=(17, 22, 4, 1), text=_("Base attack"), align=ui.ALIGN_W)
618
        ui.Label(self.win, layout=(21, 22, 5, 1), id="vAAttack", align=ui.ALIGN_E)
619
        ui.Label(self.win, layout=(17, 23, 3, 1), text=_("Base defence"), align=ui.ALIGN_W)
620
        ui.Label(self.win, layout=(20, 23, 6, 1), id="vADefence", align=ui.ALIGN_E)
621
        ui.Label(self.win, layout=(17, 24, 5, 1), text=_("Military power"), align=ui.ALIGN_W)
622
        ui.Label(self.win, layout=(22, 24, 4, 1), id="vACombatPwr", align=ui.ALIGN_E)
623
624
        ui.Label(self.win, layout=(28, 20, 5, 1), text=_("Signature"), align=ui.ALIGN_W)
625
        ui.Label(self.win, layout=(33, 20, 5, 1), id="vASignature", align=ui.ALIGN_E)
626
        ui.Label(self.win, layout=(28, 21, 5, 1), id="vSpeed", text=_("Speed"), align=ui.ALIGN_W)
627
        ui.Label(self.win, layout=(34, 21, 5, 1), id="vASpeed", align=ui.ALIGN_E)
628
        ui.Label(self.win, layout=(28, 22, 5, 1), text=_("Tanks"), align=ui.ALIGN_W)
629
        ui.Label(self.win, layout=(33, 22, 5, 1), id="vATanks", align=ui.ALIGN_E)
630
        ui.Label(self.win, layout=(28, 23, 5, 1), text=_("Max. range"), align=ui.ALIGN_W)
631
        ui.Label(self.win, layout=(33, 23, 5, 1), id="vARange", align=ui.ALIGN_E)
632
        ui.Label(self.win, layout=(28, 24, 5, 1), text=_("Constr. pts"), align=ui.ALIGN_W)
633
        ui.Label(self.win, layout=(33, 24, 5, 1), font='normal-bold', id="vACCPts", align=ui.ALIGN_E)
634
635
        # actions
636
        ui.Title(self.win, layout=(15, 25, 25, 1))
637
        ui.Button(self.win, layout=(15, 26, 5, 1), text=_("Scrap"),
638
                  id="vScrap", action="onScrap")
639
        ui.Button(self.win, layout=(35, 26, 5, 1), text=_("Construct"),
640
                  id="vConstruct", action="onConstruct", enabled=0)
641
        # status bar + submit/cancel
642
        ui.TitleButton(self.win, layout=(35, 27, 5, 1), text=_('Close'), action='onClose')
643
        ui.Title(self.win, id='vStatusBar', layout=(0, 27, 35, 1), align=ui.ALIGN_W)
644