Merge all changes from 0.9.x

This commit is contained in:
Michael Vehrs 2009-12-31 11:41:00 +00:00
parent 71f54b5575
commit 10e171681f
35 changed files with 1180 additions and 831 deletions

View File

@ -19,7 +19,7 @@
*
-->
<!-- $Revision$ -->
<!-- specification version 0.20 -->
<!-- specification version 0.21 -->
<!-- in case of incompatible changes, please update version number and
XSD schema for validation. -->
<freecol-specification>
@ -1313,7 +1313,7 @@
<event id="model.event.seeAllColonies"/>
</founding-father>
<founding-father id="model.foundingFather.hernandoDeSoto" type="exploration"
weight1="10" weight2="2" weight3="2">
weight1="5" weight2="10" weight3="5">
<modifier id="model.modifier.lineOfSightBonus" type="additive" value="1">
<scope ability-id="model.ability.navalUnit" ability-value="false"/>
</modifier>

View File

@ -19,7 +19,7 @@
*
-->
<!-- $Revision$ -->
<!-- specification version 0.20 -->
<!-- specification version 0.21 -->
<!-- in case of incompatible changes, please update version number and
XSD schema for validation. -->
<freecol-specification>

View File

@ -19,7 +19,7 @@
*
-->
<!-- $Revision$ -->
<!-- specification version 0.20 -->
<!-- specification version 0.21 -->
<!-- in case of incompatible changes, please update version number and
XSD schema for validation. -->
<freecol-specification>

View File

@ -194,7 +194,11 @@ without any changes in "Info.plist".
FreeCol uses context menus in several places. On most platforms,
context menus are opened with a click of the right mouse button. If
you have only one mouse button, holding down the \texttt{control} key
while clicking the mouse button should also work.
while clicking the mouse button should also work. Some versions of
Java on Windows are unable to display context menus that extend beyond
the game window correctly. As we are unable to fix that, we display
the context menu in the top left corner of the game window in these
cases.
\hypertarget{Compiling FreeCol}{\section{Compiling FreeCol}}
@ -725,10 +729,7 @@ possess.
\item The \Report{Continental Congress Advisor} tells you which
Founding Fathers are already present in the \hyperlink{Continental
Congress}{Continental Congress} and which Founding Father is currently
being elected. It also tells you how many Liberty Bells each of your
colonies is producing, and whether they have already built the
\hyperlink{Printing Press}{Printing Press} and the
\hyperlink{Newspaper}{Newspaper}.
being elected.
\item The \Report{Military Advisor} informs you of the deployment of
your military units, as well as the strength of the \hyperlink{Royal
Expeditionary Force}{Royal Expeditionary Force}.
@ -758,6 +759,9 @@ and which colonies produce a surplus of these materials.
important events that took place during the game, such as the first
meeting with native tribes, the foundation and abandonment of
colonies, among other things.
\item The \Report{Production Report} provides you with an overview of
the production of up to four different kinds of goods in your
colonies, as well as the buildings that produce these goods.
\end{itemize}
@ -1037,7 +1041,8 @@ The figure \ref{europe_panel_fig} represents the Europe panel.
In this panel, you can control the ships sailing between America and
Europe, as well as the ships currently docked in Europe. You can also
buy goods, recruit, purchase and train units. Units recruited,
purchased or trained are in the Docks Area in the Europe panel.
purchased or trained are visible in the Docks Area in the Europe
panel.
If a ship has set sail for Europe or America, you can change its
direction by dragging it from the Going to America box to the Going
@ -1069,7 +1074,7 @@ Units present in Europe can also be armed, mounted, equipped with
tools or blessed as missionaries in Europe. In order to select one of
these actions, you need to right click on the unit. Note that you will
have to pay for the arms, horses or tools required to equip your
units.
units. Blessing a missionary, however, is free.
In order to send a ship back to the New World, you must drag it to the
Going to America section of the Europe panel, or press the ``Set
@ -1091,12 +1096,10 @@ this panel, colonists can be assigned to cultivate tiles surrounding
the colony, to work in buildings, defend the colony against attackers
or wait outside of the colony.
The colony panel consists of several panels and control elements with
different functions. At the top of the panel, you can see a select box
displaying the name of the colony, which can be used to select a
different colony. Next to the colony's name, you can see the
production panel, which shows how much food, horses, bells and crosses
your colony is producing.
The select box at the top left of the panel displaying the name of the
colony can be used to select a different colony. Next to the colony's
name, the production panel, shows all the goods your colony is
producing.
Below colony name, you can see the area surrounding the colony to the
left and a scroll pane displaying the buildings of the colony to the
@ -1104,22 +1107,26 @@ right. You can drag and drop a unit on a tile or a building. The tiles
surrounding the colony can produce several kinds of goods, however. If
the unit is not producing the right kind of goods, you can right click
on the unit to select a different kind of work. If a tile has a red
border, then it can not be used--- it is either assigned to another
border, then it can not be used --- it is either assigned to another
colony or settlement, or is occupied by a hostile unit, or is a water
tile which can not be used until you have built \hyperlink{Dock}{docks}.
Note that if you drag a unit onto a tile used by the natives you may
be offered the chance to purchase the land.
Below the surrounding area, you can see a status panel that tells you
how many colonists support independence and how many support the
crown. Below the status panel, the port panel shows you any ships or
wagon trains in the colony. If there is at least one unit present, the
cargo panel below the port panel shows you the cargo of the selected
carrier (if any).
Below the surrounding area, you can see the population panel, which
displays the size of your colony, the number and percentage of
colonists that support independence, the number and percentage of
colonists that support the crown, as well as the current production
bonus.
Below the status panel, the port panel shows you any ships or wagon
trains in the colony. If there is at least one unit present, the cargo
panel below the port panel shows you the cargo of the selected carrier
(if any).
On the right hand side of the panel, you can see the buildings panel,
which displays an image for every building in the colony, as well as
the building or unit currenlty being built. You can see the units
the building or unit currently being built. You can see the units
working in a building, as well as its production. If you let the mouse
hover over a building, you can see a slightly larger and more detailed
view. You can click on any building in order to open the build queue
@ -2672,473 +2679,6 @@ therefore the external tax rate will be fixed at zero, with no threat of
boycotts. However, you will no longer be able to sail to your former
home port. Future versions may implement sailing to all European ports.
\hypertarget{Changing the Rules}{\chapter{Changing the Rules}}
We would like to make FreeCol configurable, so that the game engine
becomes capable of emulating many similar games. For this purpose,
we have made many of the game's features configurable.
At some point in the future, we will probably add a special rule set
editor, but at the moment, your only option is to edit the file
specification.xml directly. This file defines the abilities of units,
founding fathers, buildings, terrain types, goods and equipment, for
example. You can find this file in the \textit{data/freecol} directory.
This is still work in progress, however, and the schema for the rule
set certain to change again in the future. If you wish to develop your
own rule set, you will have to monitor FreeCol development closely.
This having been said, we are particularly interested in hearing about
problems caused by your changes to the rule set. Some dialogs might be
unable to display more types of goods than are currently defined, for
example. Or other dialogs might not recognize your new Minuteman unit
as an armed unit. Please help us improve FreeCol by telling us about
such problems.
If you have a working rule set that adds a new flavour to the game, we
will gladly distribute it along with our default rule set. If you have
ideas that can not currently be implemented, we will probably try to
remove these limitations.
If you try to modify the rule set, you are strongly encouraged to
check whether the result is still valid. You can do this by validating
the result with the command \verb$ant validate$.
\hypertarget{Modifiers and Abilities}{\section{Modifiers and Abilities}}
Most of the objects defined by the rule set can be customized via
modifiers and abilities. Abilities are boolean values (``true'' or
``false''). If the value is not explicitly stated, it defaults to
true. If an ability is not present, it defaults to false. Modifiers
define a bonus or penalty to be applied to a numeric value, such as
the number of goods produced by a unit. The modifier may be an
additive, multiplicative or a percentage modifier. Modifiers default
to ``identity'', which means they have no effect.
The code also checks that all abilities and modifiers it uses are
defined by the specification. Therefore, you must define all of them,
even if you do not use them. You can do this by setting their value to
the default value, e.g. ``false'' in the case of an ability, or ``0''
in the case of an additive modifier.
\newcommand{\ability}[1]{\index{#1}\index{Ability!#1}\hypertarget{#1}{\vspace{1em}\noindent\textbf{#1}}}
\newcommand{\modifier}[1]{\index{#1}\index{Modifier!#1}\hypertarget{#1}{\vspace{1em}\noindent\textbf{#1}}}
\newcommand{\affectsPlayer}{\\\textit{Affects: Player\\Provided by:
Nation, Nation Type, Founding Father}}
\newcommand{\affectsUnit}{\\\textit{Affects: Unit\\Provided by:
Nation, Nation Type, Founding Father, Unit Type, Equipment Type}}
\newcommand{\affectsBuilding}{\\\textit{Affects: Building\\Provided by:
Building Type}}
\newcommand{\affectsColony}{\\\textit{Affects: Colony\\Provided by:
Map}}
\newcommand{\affectsColonyTwo}{\\\textit{Affects: Colony\\Provided by:
Building Type, Nation, Nation Type, Founding Father}}
\newcommand{\affectsTile}{\\\textit{Affects: Tile\\Provided by:
Tile Type}}
\ability{model.ability.addTaxToBells}
\affectsPlayer
The player adds the current tax rate as a bonus to bells
production. The bonus is modified every time the tax increases or
decreases.
\ability{model.ability.alwaysOfferedPeace}
\affectsPlayer
The player is always offered peace in negotiations with AI players.
\ability{model.ability.ambushBonus}
\affectsUnit
The unit is granted an ambush bonus equal to the terrain's defence value.
\ability{model.ability.ambushPenalty}
\affectsUnit
The unit suffers an ambush penalty equal to the terrain's defence value.
\ability{model.ability.autoProduction}
\affectsBuilding
The building needs no units to produce goods, and will never produce
more goods than can be stored in the colony.
\ability{model.ability.automaticEquipment}
\affectsUnit
The unit automatically picks up equipment if attacked.
\ability{model.ability.automaticPromotion}
\affectsUnit
A unit that can be promoted will always be promoted when successful in
battle.
\ability{model.ability.betterForeignAffairsReport}
\affectsPlayer
The player is provided with more information about foreign powers.
\ability{model.ability.bombard}
\affectsUnit
The unit is able to bombard other units.
\ability{model.ability.bombardShips}
\affectsBuilding
The building has the ability to bombard enemy ships on adjacent tiles.
\ability{model.ability.bornInColony}
\affectsUnit
The unit can be born in a colony, provided that enough food is available.
\ability{model.ability.bornInIndianSettlement}
\affectsUnit
The unit can be born in an Indian settlement, provided that enough food is available.
\ability{model.ability.build}
\affectsBuilding
The building can build units or equipment.
\ability{model.ability.buildCustomHouse}
\affectsPlayer
The player can build custom houses.
\ability{model.ability.buildFactory}
\affectsPlayer
The player can build factories.
\ability{model.ability.canBeCaptured}
\affectsUnit
The unit can be captured. Land units that can not be captured are
destroyed, naval units that can not be captured are either sunk or
damaged.
\ability{model.ability.canBeEquipped}
\affectsUnit
The unit can be equipped.
\ability{model.ability.canNotRecruitUnit}
\affectsPlayer
The player can not recruit specified units.
\ability{model.ability.captureEquipment}
\affectsUnit
The unit can capture equipment from another unit.
\ability{model.ability.captureGoods}
\affectsUnit
The unit can capture goods from another unit.
\ability{model.ability.captureUnits}
\affectsUnit
The unit can capture enemy units.
\ability{model.ability.carryGoods}
\affectsUnit
The unit can transport goods.
\ability{model.ability.carryTreasure}
\affectsUnit
The unit can transport treasures, not treasure trains.
\ability{model.ability.carryUnits}
\affectsUnit
The unit can transport other units.
\ability{model.ability.convert}
\affectsUnit
The unit is a native convert.
\ability{model.ability.dressMissionary}
\affectsBuilding
The building can commission missionaries.
\ability{model.ability.electFoundingFather}
\affectsPlayer
The player can elect Founding Fathers.
\ability{model.ability.expertMissionary}
\affectsUnit
The unit is an expert missionary, but not necessarily commissioned.
\ability{model.ability.expertPioneer}
\affectsUnit
The unit is an expert pioneer, but not necessarily equipped with tools.
\ability{model.ability.expertScout}
\affectsUnit
The unit is an expert scout, but not necessarily equipped with horses.
\ability{model.ability.expertSoldier}
\affectsUnit
The unit is an expert soldier, but not necessarily equipped with muskets.
\ability{model.ability.expertsUseConnections}
\affectsPlayer
Experts working in factories can produce a small amount of goods even
if the raw materials are not available in the colony.
\ability{model.ability.export}
\affectsBuilding
The building can export goods to Europe directly.
\ability{model.ability.foundColony}
\affectsUnit
The unit can found new colonies.
\ability{model.ability.foundInLostCity}
\affectsUnit
The unit may be generated as the result of exploring a Lost City Rumour.
\ability{model.ability.hasPort}
\affectsColony
The colony has access to at least one water tile. This ability can not
be set by the specification, but it can be used as a required ability.
\ability{model.ability.ignoreEuropeanWars}
\affectsPlayer
The player will not be affected by the Monarch's declarations of war.
\ability{model.ability.improveTerrain}
\affectsUnit
The unit is able to improve terrain.
\ability{model.ability.independenceDeclared}
\affectsPlayer
The player has declared independence.
\ability{model.ability.mercenaryUnit}
\affectsUnit
The unit may be offered as a mercenary unit.
\ability{model.ability.missionary}
\affectsUnit
The unit is able to establish missions and incite unrest in native
settlements.
\ability{model.ability.moveToEurope}
\affectsTile
Units on the tile are able to move to Europe.
\ability{model.ability.multipleAttacks}
\affectsUnit
The unit can attack more than once.
\ability{model.ability.native}
\affectsUnit
The unit is a native unit.
\ability{model.ability.navalUnit}
\affectsUnit
The unit is a naval unit.
\ability{model.ability.pillageUnprotectedColony}
\affectsUnit
The unit is able to steal goods from and destroy buildings in an
unprotected colony.
\ability{model.ability.piracy}
\affectsUnit
The unit is a privateer.
\ability{model.ability.produceInWater}
\affectsBuilding
The building enables units to produce on water tiles.
\ability{model.ability.refUnit}
\affectsUnit
The unit can be part of the Royal Expeditionary Force.
\ability{model.ability.repairUnits}
\affectsBuilding
The building can repair units.
\ability{model.ability.royalExpeditionaryForce}
\affectsPlayer
The player is a Royal Expeditionary Force.
\ability{model.ability.rumoursAlwaysPositive}
\affectsPlayer
The player will always get positive results from exploring Lost City
Rumours.
\ability{model.ability.scoutForeignColony}
\affectsUnit
The unit can scout out foreign colonies.
\ability{model.ability.scoutIndianSettlement}
\affectsUnit
The unit can scout out native settlements.
\ability{model.ability.selectRecruit}
\affectsPlayer
The player can select a unit to recruit in Europe. This also applies
to units generated as a result of finding a Fountain of Youth.
\ability{model.ability.teach}
\affectsBuilding
The building enables experts to teach other units. However, the
building may place limits on the experience level of teachers.
\ability{model.ability.tradeWithForeignColonies}
\affectsPlayer
The player may trade goods in foreign colonies.
\ability{model.ability.undead}
\affectsUnit
The unit is an undead unit (used only in revenge mode).
\modifier{model.modifier.bombardBonus}
\affectsPlayer
The player's units are granted a bombard bonus when attacking.
\modifier{model.modifier.buildingPriceBonus}
\affectsPlayer
The player can build or buy buildings at a reduced price.
\modifier{model.modifier.defence}
\affectsUnit
The unit has a defence bonus or penalty.
\modifier{model.modifier.immigration}
\textit{Affects: Player\\Provided by: Goods Type}
Goods of this type contribute to the player's immigration points.
\modifier{model.modifier.landPaymentModifier}
\affectsPlayer
The player can buy Indian land at a reduced price.
\modifier{model.modifier.liberty}
\textit{Affects: Player\\Provided by: Goods Type}
Goods of this type contribute to the colony's and the owning player's
liberty points.
\modifier{model.modifier.lineOfSightBonus}
\affectsUnit
The unit has an increased line of sight.
\modifier{model.modifier.minimumColonySize}
\affectsColonyTwo
The population of the colony can not be voluntarily reduced below this
number. The modifier does not in any way affect a population reduction
due to starvation or other events.
\modifier{model.modifier.movementBonus}
\affectsUnit
The unit has an increased movement range.
\modifier{model.modifier.nativeAlarmModifier}
\affectsPlayer
The player generates less native alarm.
\modifier{model.modifier.nativeConvertBonus}
\affectsPlayer
The player has a greater chance of converting natives.
\modifier{model.modifier.nativeTreasureModifier}
\affectsPlayer
The player generates greater treasures when destroying native settlements.
\modifier{model.modifier.offence}
\affectsUnit
The unit has an offence bonus or penalty.
\modifier{model.modifier.religiousUnrestBonus}
\affectsPlayer
The player generates greater religious unrest in Europe.
\modifier{model.modifier.sailHighSeas}
\affectsUnit
The unit's travel time between Europe and the New World is reduced.
\modifier{model.modifier.tradeBonus}
\affectsPlayer
Prices in the player's market remain stable for longer.
\modifier{model.modifier.treasureTransportFee}
\affectsPlayer
The player pays a smaller fee for transporting treasures to Europe.
\modifier{model.modifier.warehouseStorage}
\affectsBuilding
The building increases the capacity of the warehouse.
\hypertarget{Known bugs}{\chapter{Known bugs}}

486
doc/developer.tex Normal file
View File

@ -0,0 +1,486 @@
\documentclass[12pt]{book}
\usepackage[T1]{fontenc}
\usepackage{longtable}
\usepackage{graphicx}
\usepackage{index}
\usepackage[colorlinks=true,hyperindex=true]{hyperref}
\makeindex
\begin{document}
\author{\href{http://freecol.sourceforge.net/index.php?section=8}{The FreeCol Team}}
\title{FreeCol Documentation\\Developer Guide for Version v0.9.0}
\maketitle{}
\tableofcontents
\newpage
\hypertarget{Changing the Rules}{\chapter{Changing the Rules}}
We would like to make FreeCol configurable, so that the game engine
becomes capable of emulating many similar games. For this purpose,
we have made many of the game's features configurable.
At some point in the future, we will probably add a special rule set
editor, but at the moment, your only option is to edit the file
specification.xml directly. This file defines the abilities of units,
founding fathers, buildings, terrain types, goods and equipment, for
example. You can find this file in the \textit{data/freecol} directory.
This is still work in progress, however, and the schema for the rule
set certain to change again in the future. If you wish to develop your
own rule set, you will have to monitor FreeCol development closely.
This having been said, we are particularly interested in hearing about
problems caused by your changes to the rule set. Some dialogs might be
unable to display more types of goods than are currently defined, for
example. Or other dialogs might not recognize your new Minuteman unit
as an armed unit. Please help us improve FreeCol by telling us about
such problems.
If you have a working rule set that adds a new flavour to the game, we
will gladly distribute it along with our default rule set. If you have
ideas that can not currently be implemented, we will probably try to
remove these limitations.
If you try to modify the rule set, you are strongly encouraged to
check whether the result is still valid. You can do this by validating
the result with the command \verb$ant validate$.
\hypertarget{Modifiers and Abilities}{\section{Modifiers and Abilities}}
Most of the objects defined by the rule set can be customized via
modifiers and abilities. Abilities are boolean values (``true'' or
``false''). If the value is not explicitly stated, it defaults to
true. If an ability is not present, it defaults to false. Modifiers
define a bonus or penalty to be applied to a numeric value, such as
the number of goods produced by a unit. The modifier may be an
additive, multiplicative or a percentage modifier. Modifiers default
to ``identity'', which means they have no effect.
The code also checks that all abilities and modifiers it uses are
defined by the specification. Therefore, you must define all of them,
even if you do not use them. You can do this by setting their value to
the default value, e.g. ``false'' in the case of an ability, or ``0''
in the case of an additive modifier.
\newcommand{\ability}[1]{\index{#1}\index{Ability!#1}\hypertarget{#1}{\vspace{1em}\noindent\textbf{#1}}}
\newcommand{\modifier}[1]{\index{#1}\index{Modifier!#1}\hypertarget{#1}{\vspace{1em}\noindent\textbf{#1}}}
\newcommand{\affectsPlayer}{\\\textit{Affects: Player\\Provided by:
Nation, Nation Type, Founding Father}}
\newcommand{\affectsUnit}{\\\textit{Affects: Unit\\Provided by:
Nation, Nation Type, Founding Father, Unit Type, Equipment Type}}
\newcommand{\affectsBuilding}{\\\textit{Affects: Building\\Provided by:
Building Type}}
\newcommand{\affectsColony}{\\\textit{Affects: Colony\\Provided by:
Map}}
\newcommand{\affectsColonyTwo}{\\\textit{Affects: Colony\\Provided by:
Building Type, Nation, Nation Type, Founding Father}}
\newcommand{\affectsTile}{\\\textit{Affects: Tile\\Provided by:
Tile Type}}
\ability{model.ability.addTaxToBells}
\affectsPlayer
The player adds the current tax rate as a bonus to bells
production. The bonus is modified every time the tax increases or
decreases.
\ability{model.ability.alwaysOfferedPeace}
\affectsPlayer
The player is always offered peace in negotiations with AI players.
\ability{model.ability.ambushBonus}
\affectsUnit
The unit is granted an ambush bonus equal to the terrain's defence value.
\ability{model.ability.ambushPenalty}
\affectsUnit
The unit suffers an ambush penalty equal to the terrain's defence value.
\ability{model.ability.autoProduction}
\affectsBuilding
The building needs no units to produce goods, and will never produce
more goods than can be stored in the colony.
\ability{model.ability.automaticEquipment}
\affectsUnit
The unit automatically picks up equipment if attacked.
\ability{model.ability.automaticPromotion}
\affectsUnit
A unit that can be promoted will always be promoted when successful in
battle.
\ability{model.ability.betterForeignAffairsReport}
\affectsPlayer
The player is provided with more information about foreign powers.
\ability{model.ability.bombard}
\affectsUnit
The unit is able to bombard other units.
\ability{model.ability.bombardShips}
\affectsBuilding
The building has the ability to bombard enemy ships on adjacent tiles.
\ability{model.ability.bornInColony}
\affectsUnit
The unit can be born in a colony, provided that enough food is available.
\ability{model.ability.bornInIndianSettlement}
\affectsUnit
The unit can be born in an Indian settlement, provided that enough food is available.
\ability{model.ability.build}
\affectsBuilding
The building can build units or equipment.
\ability{model.ability.buildCustomHouse}
\affectsPlayer
The player can build custom houses.
\ability{model.ability.buildFactory}
\affectsPlayer
The player can build factories.
\ability{model.ability.canBeCaptured}
\affectsUnit
The unit can be captured. Land units that can not be captured are
destroyed, naval units that can not be captured are either sunk or
damaged.
\ability{model.ability.canBeEquipped}
\affectsUnit
The unit can be equipped.
\ability{model.ability.canNotRecruitUnit}
\affectsPlayer
The player can not recruit specified units.
\ability{model.ability.captureEquipment}
\affectsUnit
The unit can capture equipment from another unit.
\ability{model.ability.captureGoods}
\affectsUnit
The unit can capture goods from another unit.
\ability{model.ability.captureUnits}
\affectsUnit
The unit can capture enemy units.
\ability{model.ability.carryGoods}
\affectsUnit
The unit can transport goods.
\ability{model.ability.carryTreasure}
\affectsUnit
The unit can transport treasures, not treasure trains.
\ability{model.ability.carryUnits}
\affectsUnit
The unit can transport other units.
\ability{model.ability.convert}
\affectsUnit
The unit is a native convert.
\ability{model.ability.dressMissionary}
\affectsBuilding
The building can commission missionaries.
\ability{model.ability.electFoundingFather}
\affectsPlayer
The player can elect Founding Fathers.
\ability{model.ability.expertMissionary}
\affectsUnit
The unit is an expert missionary, but not necessarily commissioned.
\ability{model.ability.expertPioneer}
\affectsUnit
The unit is an expert pioneer, but not necessarily equipped with tools.
\ability{model.ability.expertScout}
\affectsUnit
The unit is an expert scout, but not necessarily equipped with horses.
\ability{model.ability.expertSoldier}
\affectsUnit
The unit is an expert soldier, but not necessarily equipped with muskets.
\ability{model.ability.expertsUseConnections}
\affectsPlayer
Experts working in factories can produce a small amount of goods even
if the raw materials are not available in the colony.
\ability{model.ability.export}
\affectsBuilding
The building can export goods to Europe directly.
\ability{model.ability.foundColony}
\affectsUnit
The unit can found new colonies.
\ability{model.ability.foundInLostCity}
\affectsUnit
The unit may be generated as the result of exploring a Lost City Rumour.
\ability{model.ability.hasPort}
\affectsColony
The colony has access to at least one water tile. This ability can not
be set by the specification, but it can be used as a required ability.
\ability{model.ability.ignoreEuropeanWars}
\affectsPlayer
The player will not be affected by the Monarch's declarations of war.
\ability{model.ability.improveTerrain}
\affectsUnit
The unit is able to improve terrain.
\ability{model.ability.independenceDeclared}
\affectsPlayer
The player has declared independence.
\ability{model.ability.mercenaryUnit}
\affectsUnit
The unit may be offered as a mercenary unit.
\ability{model.ability.missionary}
\affectsUnit
The unit is able to establish missions and incite unrest in native
settlements.
\ability{model.ability.moveToEurope}
\affectsTile
Units on the tile are able to move to Europe.
\ability{model.ability.multipleAttacks}
\affectsUnit
The unit can attack more than once.
\ability{model.ability.native}
\affectsUnit
The unit is a native unit.
\ability{model.ability.navalUnit}
\affectsUnit
The unit is a naval unit.
\ability{model.ability.pillageUnprotectedColony}
\affectsUnit
The unit is able to steal goods from and destroy buildings in an
unprotected colony.
\ability{model.ability.piracy}
\affectsUnit
The unit is a privateer.
\ability{model.ability.produceInWater}
\affectsBuilding
The building enables units to produce on water tiles.
\ability{model.ability.refUnit}
\affectsUnit
The unit can be part of the Royal Expeditionary Force.
\ability{model.ability.repairUnits}
\affectsBuilding
The building can repair units.
\ability{model.ability.royalExpeditionaryForce}
\affectsPlayer
The player is a Royal Expeditionary Force.
\ability{model.ability.rumoursAlwaysPositive}
\affectsPlayer
The player will always get positive results from exploring Lost City
Rumours.
\ability{model.ability.scoutForeignColony}
\affectsUnit
The unit can scout out foreign colonies.
\ability{model.ability.scoutIndianSettlement}
\affectsUnit
The unit can scout out native settlements.
\ability{model.ability.selectRecruit}
\affectsPlayer
The player can select a unit to recruit in Europe. This also applies
to units generated as a result of finding a Fountain of Youth.
\ability{model.ability.teach}
\affectsBuilding
The building enables experts to teach other units. However, the
building may place limits on the experience level of teachers.
\ability{model.ability.tradeWithForeignColonies}
\affectsPlayer
The player may trade goods in foreign colonies.
\ability{model.ability.undead}
\affectsUnit
The unit is an undead unit (used only in revenge mode).
\modifier{model.modifier.bombardBonus}
\affectsPlayer
The player's units are granted a bombard bonus when attacking.
\modifier{model.modifier.buildingPriceBonus}
\affectsPlayer
The player can build or buy buildings at a reduced price.
\modifier{model.modifier.defence}
\affectsUnit
The unit has a defence bonus or penalty.
\modifier{model.modifier.immigration}
\textit{Affects: Player\\Provided by: Goods Type}
Goods of this type contribute to the player's immigration points.
\modifier{model.modifier.landPaymentModifier}
\affectsPlayer
The player can buy Indian land at a reduced price.
\modifier{model.modifier.liberty}
\textit{Affects: Player\\Provided by: Goods Type}
Goods of this type contribute to the colony's and the owning player's
liberty points.
\modifier{model.modifier.lineOfSightBonus}
\affectsUnit
The unit has an increased line of sight.
\modifier{model.modifier.minimumColonySize}
\affectsColonyTwo
The population of the colony can not be voluntarily reduced below this
number. The modifier does not in any way affect a population reduction
due to starvation or other events.
\modifier{model.modifier.movementBonus}
\affectsUnit
The unit has an increased movement range.
\modifier{model.modifier.nativeAlarmModifier}
\affectsPlayer
The player generates less native alarm.
\modifier{model.modifier.nativeConvertBonus}
\affectsPlayer
The player has a greater chance of converting natives.
\modifier{model.modifier.nativeTreasureModifier}
\affectsPlayer
The player generates greater treasures when destroying native settlements.
\modifier{model.modifier.offence}
\affectsUnit
The unit has an offence bonus or penalty.
\modifier{model.modifier.religiousUnrestBonus}
\affectsPlayer
The player generates greater religious unrest in Europe.
\modifier{model.modifier.sailHighSeas}
\affectsUnit
The unit's travel time between Europe and the New World is reduced.
\modifier{model.modifier.tradeBonus}
\affectsPlayer
Prices in the player's market remain stable for longer.
\modifier{model.modifier.treasureTransportFee}
\affectsPlayer
The player pays a smaller fee for transporting treasures to Europe.
\modifier{model.modifier.warehouseStorage}
\affectsBuilding
The building increases the capacity of the warehouse.
\printindex
\end{document}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 KiB

After

Width:  |  Height:  |  Size: 650 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 993 KiB

After

Width:  |  Height:  |  Size: 594 KiB

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- XSD for specification version 0.20 -->
<!-- XSD for specification version 0.21 -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="freecol-specification">
<xs:complexType>

View File

@ -176,8 +176,6 @@ public final class Canvas extends JDesktopPane {
private static final Integer STATUS_LAYER = JLayeredPane.POPUP_LAYER;
//private static final int EXIT = 0, RECRUIT = 1, PURCHASE = 2, TRAIN = 3, UNLOAD = 4;
/**
* To save the most recently open dialog in Europe
* (<code>RecruitDialog</code>, <code>PurchaseDialog</code>, <code>TrainDialog</code>)
@ -1429,8 +1427,7 @@ public final class Canvas extends JDesktopPane {
*/
public void showColonyPanel(Colony colony) {
freeColClient.getGUI().stopBlinking();
ColonyPanel colonyPanel = new ColonyPanel(this);
colonyPanel.initialize(colony);
ColonyPanel colonyPanel = new ColonyPanel(colony, this);
addAsFrame(colonyPanel);
colonyPanel.requestFocus();
}
@ -1529,7 +1526,10 @@ public final class Canvas extends JDesktopPane {
public void remove(Component comp, boolean update) {
if (comp == null) {
return;
} else if (comp instanceof FreeColPanel) {
((FreeColPanel) comp).setSavedSize(comp.getSize());
}
final Rectangle updateBounds = comp.getBounds();
final JInternalFrame frame = getInternalFrame(comp);
if (frame != null && frame != comp) {

View File

@ -2572,23 +2572,17 @@ public final class GUI {
* are none.
*/
public int getBreakingPoint(String string) {
int center = string.length() / 2;
int bestIndex = string.indexOf(' ');
int index = 0;
while (index != -1 && index != bestIndex) {
if (Math.abs(center-index) < Math.abs(center-bestIndex)) {
bestIndex = index;
int center = string.length() / 2;
for (int offset = 0; offset < center; offset++) {
if (string.charAt(center + offset) == ' ') {
return center + offset;
} else if (string.charAt(center - offset) == ' ') {
index = center - offset;
return center - offset;
}
index = string.indexOf(' ', bestIndex);
}
if (bestIndex == 0 || bestIndex == string.length()) {
return -1;
} else {
return bestIndex;
}
return -1;
}
/**

View File

@ -19,11 +19,13 @@
package net.sf.freecol.client.gui;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
@ -31,6 +33,7 @@ import java.util.logging.Logger;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import net.sf.freecol.FreeCol;
import net.sf.freecol.client.FreeColClient;
@ -38,6 +41,7 @@ import net.sf.freecol.client.gui.action.UnloadAction;
import net.sf.freecol.client.gui.i18n.Messages;
import net.sf.freecol.client.gui.panel.ChoiceItem;
import net.sf.freecol.client.gui.panel.IndianSettlementPanel;
import net.sf.freecol.client.gui.panel.ReportPanel;
import net.sf.freecol.client.gui.panel.TilePanel;
import net.sf.freecol.common.model.Colony;
import net.sf.freecol.common.model.FreeColObject;
@ -101,7 +105,8 @@ public final class TilePopup extends JPopupMenu {
if (activeUnit.isOffensiveUnit() &&
activeUnit.getTile().isAdjacent(tile) &&
activeUnit.getMoveType(tile) == MoveType.ATTACK) {
CombatOdds combatOdds = activeUnit.getGame().getCombatModel().calculateCombatOdds(activeUnit, tile.getDefendingUnit(activeUnit));
CombatOdds combatOdds = activeUnit.getGame().getCombatModel()
.calculateCombatOdds(activeUnit, tile.getDefendingUnit(activeUnit));
String victoryPercent;
//If attacking a settlement, the true odds are never known because units may be hidden within
@ -161,7 +166,10 @@ public final class TilePopup extends JPopupMenu {
int lineCount = 0;
int maxUnits = UNIT_LINES_IN_FIRST_MENU;
Container currentMenu = this;
for (final Unit currentUnit : tile.getUnitList()) {
boolean moreUnits = false;
List<Unit> units = new ArrayList<Unit>(tile.getUnitList());
Collections.sort(units, ReportPanel.unitTypeComparator);
for (final Unit currentUnit : units) {
if (lineCount > maxUnits) {
JMenu more = new JMenu(Messages.message("more"));
@ -169,6 +177,7 @@ public final class TilePopup extends JPopupMenu {
more.setOpaque(false);
currentMenu.add(more);
currentMenu = more;
moreUnits = true;
lineCount = 0;
maxUnits = UNIT_LINES_IN_OTHER_MENUS;
}
@ -176,24 +185,22 @@ public final class TilePopup extends JPopupMenu {
lineCount += addUnit(currentMenu, currentUnit, !currentUnit.isUnderRepair(), false);
}
if (tile.getUnitCount() > 0) {
if (tile.getUnitCount() > 1) {
if (tile.getUnitCount() > 1) {
if (moreUnits) {
addSeparator();
JMenuItem activateAllItem = new JMenuItem(Messages.message("activateAllUnits"));
activateAllItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
Unit lastUnit = null;
for (Unit unit: tile.getUnitList()) {
freeColClient.getInGameController().clearOrders(unit);
lastUnit = unit;
}
gui.setActiveUnit(lastUnit);
}
}
);
add(activateAllItem);
}
addSeparator();
JMenuItem activateAllItem = new JMenuItem(Messages.message("activateAllUnits"));
activateAllItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
Unit lastUnit = null;
for (Unit unit: tile.getUnitList()) {
freeColClient.getInGameController().clearOrders(unit);
lastUnit = unit;
}
gui.setActiveUnit(lastUnit);
}
});
add(activateAllItem);
}
// START DEBUG
@ -322,6 +329,10 @@ public final class TilePopup extends JPopupMenu {
add(dumpItem);
}
// END DEBUG
Component lastComponent = getComponent(getComponentCount() - 1);
if (lastComponent instanceof JSeparator) {
remove(lastComponent);
}
}
/**

View File

@ -2114,6 +2114,7 @@ report.sonsOfLiberty=Sons of Liberty
report.stance=Stance
report.50percent=Turns to reach 50%
report.100percent=Turns to reach 100%
report.nextMember=Turns to increase rebels
report.requirements.noExpert=%colony% is producing %goods%, but has no %unit%.
report.requirements.missingGoods=%colony% is producing %goods%, but requires more %input%.

View File

@ -22,6 +22,7 @@ package net.sf.freecol.client.gui.panel;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
@ -39,6 +40,7 @@ import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@ -46,7 +48,6 @@ import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.ComponentInputMap;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JButton;
@ -55,6 +56,7 @@ import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolTip;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
@ -67,6 +69,8 @@ import net.sf.freecol.client.ClientOptions;
import net.sf.freecol.client.gui.Canvas;
import net.sf.freecol.client.gui.GUI;
import net.sf.freecol.client.gui.i18n.Messages;
import net.sf.freecol.common.Specification;
import net.sf.freecol.common.model.AbstractGoods;
import net.sf.freecol.common.model.BuildableType;
import net.sf.freecol.common.model.Building;
import net.sf.freecol.common.model.Colony;
@ -115,8 +119,12 @@ public final class ColonyPanel extends FreeColPanel implements ActionListener,Pr
private final JLabel popLabel = new JLabel();
private final JLabel royalistMemberLabel = new JLabel();
private final JPanel productionPanel = new JPanel();
private final JPanel populationPanel = new JPanel();
private final JPanel rightProductionPanel = new JPanel();
private final JPanel populationPanel = new JPanel() {
public JToolTip createToolTip() {
return new RebelToolTip(colony, getCanvas());
}
};
private final JComboBox nameBox;
@ -152,13 +160,18 @@ public final class ColonyPanel extends FreeColPanel implements ActionListener,Pr
private static final Font hugeFont = new Font("Dialog", Font.BOLD, 24);
/**
* The saved size of this panel.
*/
private static Dimension savedSize = null;
/**
* The constructor for the panel.
*
* @param parent The parent of this panel
*/
public ColonyPanel(Canvas parent) {
public ColonyPanel(Colony colony, Canvas parent) {
super(parent);
setFocusCycleRoot(true);
@ -179,9 +192,10 @@ public final class ColonyPanel extends FreeColPanel implements ActionListener,Pr
fillInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_L, 0, true), "released");
SwingUtilities.replaceUIInputMap(fillButton, JComponent.WHEN_IN_FOCUSED_WINDOW, fillInputMap);
productionPanel.setOpaque(false);
rightProductionPanel.setOpaque(false);
populationPanel.setOpaque(false);
populationPanel.setToolTipText(" ");
populationPanel.setLayout(new MigLayout("wrap 5, fill, insets 0",
"[][]:push[center]:push[right][]", ""));
populationPanel.add(rebelShield, "bottom");
@ -245,6 +259,17 @@ public final class ColonyPanel extends FreeColPanel implements ActionListener,Pr
// Make the colony label
nameBox = new JComboBox();
nameBox.setFont(smallHeaderFont);
List<Colony> settlements = colony.getOwner().getColonies();
sortColonies(settlements);
for (Colony aColony : settlements) {
nameBox.addItem(aColony);
}
nameBox.setSelectedItem(colony);
nameBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
initialize((Colony) nameBox.getSelectedItem());
}
});
buildingsScroll.setAutoscrolls(true);
@ -281,8 +306,8 @@ public final class ColonyPanel extends FreeColPanel implements ActionListener,Pr
setLayout(new MigLayout("fill, wrap 2", "[390!][fill]", ""));
add(nameBox, "growx, height 48:");
add(productionPanel, "align center");
add(nameBox, "height 48:, grow");
add(rightProductionPanel);
add(tilesScroll, "width 390!, height 200!, top");
add(buildingsScroll, "span 1 3, grow 200");
add(populationPanel, "grow");
@ -295,7 +320,10 @@ public final class ColonyPanel extends FreeColPanel implements ActionListener,Pr
add(warehouseButton);
add(exitButton);
setSize(parent.getWidth(), parent.getHeight());
initialize(colony);
if (savedSize != null) {
setPreferredSize(savedSize);
}
}
@ -304,6 +332,24 @@ public final class ColonyPanel extends FreeColPanel implements ActionListener,Pr
exitButton.requestFocus();
}
/**
* Get the <code>SavedSize</code> value.
*
* @return a <code>Dimension</code> value
*/
public final Dimension getSavedSize() {
return savedSize;
}
/**
* Set the <code>SavedSize</code> value.
*
* @param newSavedSize The new SavedSize value.
*/
public final void setSavedSize(final Dimension newSavedSize) {
this.savedSize = newSavedSize;
}
/**
* Initialize the data on the window. This is the same as calling:
* <code>initialize(colony, game, null)</code>.
@ -331,9 +377,6 @@ public final class ColonyPanel extends FreeColPanel implements ActionListener,Pr
+ ".coat-of-arms.image", 0.5)));
royalistShield.setIcon(new ImageIcon(ResourceManager.getImage(colony.getOwner().getNation().getRefNation().getId()
+ ".coat-of-arms.image", 0.5)));
popLabel.setText(Messages.message("colonyPanel.populationLabel", "%number%",
Integer.toString(colony.getUnitCount())));
// Set listeners and transfer handlers
outsideColonyPanel.removeMouseListener(releaseListener);
inPortPanel.removeMouseListener(releaseListener);
@ -394,11 +437,9 @@ public final class ColonyPanel extends FreeColPanel implements ActionListener,Pr
tilePanel.initialize();
updateNameBox();
updateProductionPanel();
updateSoLLabel();
outsideColonyPanel.setColony(colony);
}
@ -428,20 +469,35 @@ public final class ColonyPanel extends FreeColPanel implements ActionListener,Pr
* Updates the SoL membership label.
*/
private void updateSoLLabel() {
if (getColony() == null) {
// Apparently this can happen
logger.warning("Colony panel has 'null' colony.");
return;
}
int population = colony.getUnitCount();
int members = getColony().getMembers();
int rebels = getColony().getSoL();
rebelLabel.setText(Messages.message("colonyPanel.rebelLabel", "%number%",
Integer.toString(members)));
String rebelNumber = Messages.message("colonyPanel.rebelLabel", "%number%",
Integer.toString(members));
String royalistNumber = Messages.message("colonyPanel.royalistLabel", "%number%",
Integer.toString(population - members));
/*
* TODO : remove compatibility code sometime after 0.9.1
*
* The string templates were changed from percentages to
* absolute numbers shortly before 0.9.0, so that translators
* had no chance to catch up.
*/
if (rebelNumber.endsWith("%")) {
rebelNumber = rebelNumber.substring(0, rebelNumber.length() - 1);
}
if (royalistNumber.endsWith("%")) {
royalistNumber = royalistNumber.substring(0, royalistNumber.length() - 1);
}
// end TODO
popLabel.setText(Messages.message("colonyPanel.populationLabel", "%number%",
Integer.toString(population)));
rebelLabel.setText(rebelNumber);
rebelMemberLabel.setText(Integer.toString(rebels) + "%");
bonusLabel.setText(Messages.message("colonyPanel.bonusLabel", "%number%",
Integer.toString(getColony().getProductionBonus())));
royalistLabel.setText(Messages.message("colonyPanel.royalistLabel", "%number%",
Integer.toString(getColony().getUnitCount() - members)));
royalistLabel.setText(royalistNumber);
royalistMemberLabel.setText(Integer.toString(getColony().getTory()) + "%");
}
@ -457,24 +513,6 @@ public final class ColonyPanel extends FreeColPanel implements ActionListener,Pr
tilePanel.initialize();
}
public void updateNameBox() {
if (getColony() == null) {
// Apparently this can happen
return;
} else if (((DefaultComboBoxModel) nameBox.getModel()).getSize() == 0) {
List<Colony> settlements = getColony().getOwner().getColonies();
sortColonies(settlements);
for (Colony colony : settlements) {
nameBox.addItem(colony);
}
nameBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
initialize((Colony) nameBox.getSelectedItem());
}
});
}
}
private void sortBuildings(List<Building> buildings) {
Collections.sort(buildings, Building.getBuildingComparator());
}
@ -484,66 +522,50 @@ public final class ColonyPanel extends FreeColPanel implements ActionListener,Pr
}
public void updateProductionPanel() {
productionPanel.removeAll();
rightProductionPanel.removeAll();
final int foodFarmsProduction = colony.getProductionOf(Goods.FOOD);
final int foodFishProduction = colony.getProductionOf(Goods.FISH);
final int humanFoodConsumption = colony.getFoodConsumption();
final int horsesProduced = colony.getGoodsCount(Goods.HORSES) <= 0 ?
0 : colony.getProductionOf(Goods.HORSES);
final int bells = colony.getProductionOf(Goods.BELLS);
final int crosses = colony.getProductionOf(Goods.CROSSES);
int foodProduction = foodFarmsProduction + foodFishProduction;
// The food that is used. If not enough food is produced, the
// complete production. Horses consume 1 food each, so they
// need to be added to the used food.
// Fish should be consumed preferably, to allow surplus for production of horses
final int usedFood = Math.min(humanFoodConsumption, foodProduction) + horsesProduced;
final int usedFish = colony.getFoodConsumptionByType(Goods.FISH);
final int usedCorn = Math.max(usedFood - usedFish, 0);
if (usedFish == 0) {
ProductionLabel label = new ProductionLabel(Goods.FOOD, usedFood, getCanvas());
label.setToolTipPrefix(Messages.message("totalProduction"));
productionPanel.add(label);
} else {
ProductionMultiplesLabel label = new ProductionMultiplesLabel(Goods.FOOD, usedCorn,
Goods.FISH, usedFish, getCanvas());
label.setToolTipPrefix(Messages.message("totalProduction"));
productionPanel.add(label);
List<AbstractGoods> foodProduction = new ArrayList<AbstractGoods>();
List<AbstractGoods> surplusProduction = new ArrayList<AbstractGoods>();
for (GoodsType goodsType : Specification.getSpecification().getGoodsTypeList()) {
int production = colony.getProductionOf(goodsType);
if (production != 0) {
if (goodsType.isFoodType()) {
int surplus = production - colony.getFoodConsumptionByType(goodsType);
foodProduction.add(new AbstractGoods(goodsType, production));
surplusProduction.add(new AbstractGoods(goodsType, surplus));
} else if (goodsType.isBreedable()) {
ProductionLabel horseLabel = new ProductionLabel(goodsType, production, getCanvas());
horseLabel.setMaxGoodsIcons(1);
rightProductionPanel.add(horseLabel);
} else if (goodsType.isImmigrationType() || goodsType.isLibertyType()) {
int consumption = colony.getConsumption(goodsType);
ProductionLabel bellsLabel = new ProductionLabel(goodsType, production, getCanvas());
bellsLabel.setToolTipPrefix(Messages.message("totalProduction"));
if (consumption != 0) {
int surplus = production - consumption;
ProductionLabel surplusLabel = new ProductionLabel(goodsType, surplus, getCanvas());
surplusLabel.setToolTipPrefix(Messages.message("surplusProduction"));
rightProductionPanel.add(surplusLabel, 0);
}
rightProductionPanel.add(bellsLabel, 0);
} else {
production = colony.getProductionNetOf(goodsType);
rightProductionPanel.add(new ProductionLabel(goodsType, production, getCanvas()));
}
}
}
int remainingCorn = foodFarmsProduction - usedCorn;
final int remainingFish = foodFishProduction - usedFish;
int surplusFood = foodProduction - humanFoodConsumption - horsesProduced;
remainingCorn = Math.min(surplusFood, remainingCorn);
ProductionMultiplesLabel surplusLabel =
new ProductionMultiplesLabel(Goods.FOOD, remainingCorn, Goods.FISH, remainingFish, getCanvas());
new ProductionMultiplesLabel(surplusProduction, getCanvas());
surplusLabel.setDrawPlus(true);
surplusLabel.setToolTipPrefix(Messages.message("surplusProduction"));
productionPanel.add(surplusLabel);
rightProductionPanel.add(surplusLabel, 0);
if (horsesProduced != 0) {
// Skip the horses label if there is no stock
ProductionLabel horseLabel = new ProductionLabel(Goods.HORSES, horsesProduced, getCanvas());
horseLabel.setMaxGoodsIcons(1);
productionPanel.add(horseLabel);
}
ProductionMultiplesLabel label = new ProductionMultiplesLabel(foodProduction, getCanvas());
label.setToolTipPrefix(Messages.message("totalProduction"));
rightProductionPanel.add(label, 0);
ProductionLabel bellsLabel = new ProductionLabel(Goods.BELLS, bells, getCanvas());
bellsLabel.setToolTipPrefix(Messages.message("totalProduction"));
productionPanel.add(bellsLabel);
int surplusBells = bells - colony.getConsumption(Goods.BELLS);
ProductionLabel bellsSurplusLabel = new ProductionLabel(Goods.BELLS, surplusBells, getCanvas());
bellsSurplusLabel.setToolTipPrefix(Messages.message("surplusProduction"));
productionPanel.add(bellsSurplusLabel);
productionPanel.add(new ProductionLabel(Goods.CROSSES, crosses, getCanvas()));
productionPanel.revalidate();
rightProductionPanel.revalidate();
}
/**

View File

@ -113,6 +113,12 @@ public final class ColopediaPanel extends FreeColPanel implements TreeSelectionL
private JTree tree;
/**
* The saved size of this panel.
*/
private static Dimension savedSize = new Dimension(850, 600);
/**
* The constructor that will add the items to this panel.
*
@ -123,7 +129,7 @@ public final class ColopediaPanel extends FreeColPanel implements TreeSelectionL
none = Messages.message("none");
setLayout(new MigLayout("", "[]unrelated[grow, fill]", "[][grow, fill][]"));
setLayout(new MigLayout("fill", "[200:]unrelated[550:, grow, fill]", "[][grow, fill][]"));
header = getDefaultHeader(Messages.message("menuBar.colopedia"));
add(header, "span, align center");
@ -139,29 +145,36 @@ public final class ColopediaPanel extends FreeColPanel implements TreeSelectionL
detailPanel = new JPanel();
detailPanel.setOpaque(false);
JScrollPane detail = new JScrollPane(detailPanel,
JScrollPane detail = new JScrollPane(detailPanel,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
detail.getVerticalScrollBar().setUnitIncrement(16);
detail.getViewport().setOpaque(false);
add(detail);
add(detail, "grow");
add(okButton, "newline 20, span, tag ok");
setSize(getPreferredSize());
setPreferredSize(savedSize);
}
@Override
public Dimension getMinimumSize() {
return new Dimension(850, 600);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(850, getCanvas().getHeight() - 100);
/**
* Get the <code>SavedSize</code> value.
*
* @return a <code>Dimension</code> value
*/
public final Dimension getSavedSize() {
return savedSize;
}
/**
* Set the <code>SavedSize</code> value.
*
* @param newSavedSize The new SavedSize value.
*/
public final void setSavedSize(final Dimension newSavedSize) {
this.savedSize = newSavedSize;
}
/**
* Prepares this panel to be displayed.
@ -633,7 +646,7 @@ public final class ColopediaPanel extends FreeColPanel implements TreeSelectionL
return;
}
detailPanel.setLayout(new MigLayout("wrap 4, fillx, gap 20", "[][]push[][]", ""));
detailPanel.setLayout(new MigLayout("wrap 4, gap 20", "[][]push[][]", ""));
String movementCost = String.valueOf(tileType.getBasicMoveCost() / 3);
String defenseBonus = none;
@ -693,7 +706,7 @@ public final class ColopediaPanel extends FreeColPanel implements TreeSelectionL
}
detailPanel.add(new JLabel(Messages.message("colopedia.terrain.description")));
detailPanel.add(getDefaultTextArea(tileType.getDescription()), "span, growx");
detailPanel.add(getDefaultTextArea(tileType.getDescription(), 20), "span, growx");
detailPanel.revalidate();
detailPanel.repaint();
@ -746,7 +759,7 @@ public final class ColopediaPanel extends FreeColPanel implements TreeSelectionL
detailPanel.add(goodsPanel);
detailPanel.add(new JLabel(Messages.message("colopedia.resource.description")), "newline 20");
detailPanel.add(getDefaultTextArea(type.getDescription()), "growx");
detailPanel.add(getDefaultTextArea(type.getDescription(), 20), "growx");
detailPanel.revalidate();
detailPanel.repaint();
@ -881,7 +894,7 @@ public final class ColopediaPanel extends FreeColPanel implements TreeSelectionL
detailPanel.add(new JLabel(Messages.message("colopedia.unit.description")),
"newline 20");
detailPanel.add(getDefaultTextArea(type.getDescription()), "growx");
detailPanel.add(getDefaultTextArea(type.getDescription(), 20), "growx");
detailPanel.revalidate();
detailPanel.repaint();
@ -953,7 +966,7 @@ public final class ColopediaPanel extends FreeColPanel implements TreeSelectionL
}
detailPanel.add(new JLabel(Messages.message("colopedia.goods.description")));
detailPanel.add(getDefaultTextArea(type.getDescription()), "growx");
detailPanel.add(getDefaultTextArea(type.getDescription(), 20), "growx");
detailPanel.revalidate();
detailPanel.repaint();
@ -1108,7 +1121,7 @@ public final class ColopediaPanel extends FreeColPanel implements TreeSelectionL
// Notes
detailPanel.add(new JLabel(Messages.message("colopedia.buildings.notes")), "newline 20, top");
detailPanel.add(getDefaultTextArea(buildingType.getDescription()), "growx");
detailPanel.add(getDefaultTextArea(buildingType.getDescription(), 20), "growx");
detailPanel.revalidate();
detailPanel.repaint();
@ -1146,8 +1159,8 @@ public final class ColopediaPanel extends FreeColPanel implements TreeSelectionL
String text = Messages.message(father.getDescription()) + "\n\n" + "["
+ Messages.message(father.getBirthAndDeath()) + "] "
+ Messages.message(father.getText());
JTextArea description = getDefaultTextArea(text);
detailPanel.add(description, "top, growx, shrink");
JTextArea description = getDefaultTextArea(text, 20);
detailPanel.add(description, "top, growx");
detailPanel.revalidate();
detailPanel.repaint();

View File

@ -21,6 +21,7 @@ package net.sf.freecol.client.gui.panel;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Image;
@ -131,12 +132,37 @@ public class FreeColPanel extends JPanel implements ActionListener {
BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, LINK_COLOR),
BorderFactory.createEmptyBorder(2, 2, 2, 2));
private static final FreeColImageBorder imageBorder =
new FreeColImageBorder(ResourceManager.getImage("menuborder.n.image"),
ResourceManager.getImage("menuborder.w.image"),
ResourceManager.getImage("menuborder.s.image"),
ResourceManager.getImage("menuborder.e.image"),
ResourceManager.getImage("menuborder.nw.image"),
ResourceManager.getImage("menuborder.ne.image"),
ResourceManager.getImage("menuborder.sw.image"),
ResourceManager.getImage("menuborder.se.image"));
protected boolean editable = true;
protected JButton okButton = new JButton(Messages.message("ok"));
protected static StyleContext styleContext = null;
protected static StyleContext styleContext = new StyleContext();
static {
Style defaultStyle = styleContext.getDefaultStyleContext()
.getStyle(StyleContext.DEFAULT_STYLE);
Style regular = styleContext.addStyle("regular", defaultStyle);
StyleConstants.setFontFamily(regular, "Dialog");
StyleConstants.setBold(regular, true);
StyleConstants.setFontSize(regular, 12);
Style buttonStyle = styleContext.addStyle("button", regular);
StyleConstants.setForeground(buttonStyle, LINK_COLOR);
Style right = styleContext.addStyle("right", regular);
StyleConstants.setAlignment(right, StyleConstants.ALIGN_RIGHT);
}
/**
* Constructor.
@ -157,18 +183,8 @@ public class FreeColPanel extends JPanel implements ActionListener {
this.canvas = parent;
setFocusCycleRoot(true);
Image menuborderN = ResourceManager.getImage("menuborder.n.image");
Image menuborderNW = ResourceManager.getImage("menuborder.nw.image");
Image menuborderNE = ResourceManager.getImage("menuborder.ne.image");
Image menuborderW = ResourceManager.getImage("menuborder.w.image");
Image menuborderE = ResourceManager.getImage("menuborder.e.image");
Image menuborderS = ResourceManager.getImage("menuborder.s.image");
Image menuborderSW = ResourceManager.getImage("menuborder.sw.image");
Image menuborderSE = ResourceManager.getImage("menuborder.se.image");
final FreeColImageBorder imageBorder = new FreeColImageBorder(menuborderN, menuborderW, menuborderS,
menuborderE, menuborderNW, menuborderNE, menuborderSW, menuborderSE);
setBorder(BorderFactory.createCompoundBorder(imageBorder,
BorderFactory.createEmptyBorder(margin, margin,margin,margin)));
BorderFactory.createEmptyBorder(margin, margin, margin, margin)));
// See the message of Ulf Onnen for more information about the presence
// of this fake mouse listener.
@ -181,6 +197,15 @@ public class FreeColPanel extends JPanel implements ActionListener {
setCancelComponent(okButton);
}
/**
* Set the <code>SavedSize</code> value.
*
* @param newSavedSize The new SavedSize value.
*/
public void setSavedSize(final Dimension newSavedSize) {
// override this if you want a panel to remember its size
}
/**
* Get the <code>Canvas</code> value.
*
@ -242,18 +267,30 @@ public class FreeColPanel extends JPanel implements ActionListener {
return editable;
}
/**
* The OK button requests focus.
*
*/
public void requestFocus() {
okButton.requestFocus();
}
/**
* Get a JTextPane with default styles.
*
* @return a <code>JTextPane</code> value
*/
public static JTextPane getDefaultTextPane() {
return getDefaultTextPane(null);
}
/**
* Get a JTextPane with default styles and given text.
*
* @param text a <code>String</code> value
* @return a <code>JTextPane</code> value
*/
public static JTextPane getDefaultTextPane(String text) {
if (styleContext == null) {
styleContext = createStyleContext();
}
JTextPane textPane = new JTextPane(new DefaultStyledDocument(styleContext));
textPane.setOpaque(false);
textPane.setEditable(false);
@ -264,24 +301,6 @@ public class FreeColPanel extends JPanel implements ActionListener {
}
private static StyleContext createStyleContext() {
StyleContext defaultContext = new StyleContext();
Style defaultStyle = defaultContext.getDefaultStyleContext()
.getStyle(StyleContext.DEFAULT_STYLE);
Style regular = defaultContext.addStyle("regular", defaultStyle);
StyleConstants.setFontFamily(regular, "Dialog");
StyleConstants.setBold(regular, true);
StyleConstants.setFontSize(regular, 12);
Style buttonStyle = defaultContext.addStyle("button", regular);
StyleConstants.setForeground(buttonStyle, LINK_COLOR);
Style right = defaultContext.addStyle("right", regular);
StyleConstants.setAlignment(right, StyleConstants.ALIGN_RIGHT);
return defaultContext;
}
/**
* Returns a text area with standard settings suitable for use in FreeCol
@ -294,6 +313,7 @@ public class FreeColPanel extends JPanel implements ActionListener {
public static JTextArea getDefaultTextArea(String text) {
return getDefaultTextArea(text, COLUMNS);
}
/**
* Returns a text area with standard settings suitable for use in FreeCol
* dialogs.
@ -316,6 +336,15 @@ public class FreeColPanel extends JPanel implements ActionListener {
return textArea;
}
/**
* Return a button suitable for linking to another panel
* (e.g. ColopediaPanel).
*
* @param text a <code>String</code> value
* @param icon an <code>Icon</code> value
* @param action a <code>String</code> value
* @return a <code>JButton</code> value
*/
public static JButton getLinkButton(String text, Icon icon, String action) {
JButton button = new JButton(text, icon);
button.setMargin(emptyMargin);
@ -341,6 +370,11 @@ public class FreeColPanel extends JPanel implements ActionListener {
return header;
}
/**
* Make the given button the CANCEL button.
*
* @param cancelButton an <code>AbstractButton</code> value
*/
public void setCancelComponent(AbstractButton cancelButton) {
if (cancelButton == null) {
throw new NullPointerException();
@ -354,7 +388,7 @@ public class FreeColPanel extends JPanel implements ActionListener {
}
/**
* Registers enter key for a jbutton.
* Registers enter key for a JButton.
*
* @param button
*/
@ -367,10 +401,20 @@ public class FreeColPanel extends JPanel implements ActionListener {
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), JComponent.WHEN_FOCUSED);
}
/**
* Returns the default modifier value format.
*
* @return a <code>DecimalFormat</code> value
*/
public static final DecimalFormat getModifierFormat() {
return modifierFormat;
}
/**
* Sort the given modifiers according to type.
*
* @return a sorted Set of Modifiers
*/
public Set<Modifier> sortModifiers(Set<Modifier> result) {
EnumMap<Modifier.Type, List<Modifier>> modifierMap =
new EnumMap<Modifier.Type, List<Modifier>>(Modifier.Type.class);

View File

@ -199,7 +199,9 @@ public class FreeColProgressBar extends JPanel {
String stepSignal = (step < 0) ? "-" : "+";
String progressString = String.valueOf(value) + stepSignal + Math.abs(step) + "/" + max;
String turnsString = Messages.message("notApplicable.short");
if (max > value && step > 0) {
if (max <= value) {
turnsString = "0";
} else if (step > 0) {
// There is progress, find how many turns necessary with current production
int turns = (max - value) / step;
if ((max - value) % step > 0) {

View File

@ -424,18 +424,28 @@ public final class InfoPanel extends FreeColPanel {
*/
public class EndTurnPanel extends JPanel {
private JLabel endTurnLabel = new JLabel(Messages.message("infoPanel.endTurnPanel.text"), JLabel.CENTER);
private JButton endTurnButton = new JButton(Messages.message("infoPanel.endTurnPanel.endTurnButton"));
public EndTurnPanel() {
super(new FlowLayout(FlowLayout.CENTER, 10, 10));
add(endTurnLabel);
super(new MigLayout("wrap 1, center", "[center]", ""));
String labelString = Messages.message("infoPanel.endTurnPanel.text");
int width = getFontMetrics(getFont()).stringWidth(labelString);
if (width > 150 ) {
int index = getCanvas().getGUI().getBreakingPoint(labelString);
if (index > 0) {
add(new JLabel(labelString.substring(0, index)));
add(new JLabel(labelString.substring(index + 1)));
} else {
add(new JLabel(labelString));
}
} else {
add(new JLabel(labelString));
}
add(endTurnButton);
setOpaque(false);
setSize(230, endTurnLabel.getPreferredSize().height + endTurnButton.getPreferredSize().height + 30);
setSize(getPreferredSize());
/*
* TODO: The action listener does not work, because this button

View File

@ -460,11 +460,12 @@ public final class ProductionLabel extends JComponent {
int coverage = pixelsPerIcon * (drawImageCount - 1) + iconWidth;
int leftOffset = 0;
if (centered && coverage < stringWidth) {
leftOffset = (stringWidth - coverage)/2;
int width = Math.max(getWidth(), Math.max(stringWidth, coverage));
if (centered && coverage < width) {
leftOffset = (width - coverage)/2;
}
int width = Math.max(stringWidth, coverage);
int height = Math.max(getHeight(), goodsIcon.getImage().getHeight(null));
setSize(new Dimension(width, height));
@ -475,7 +476,7 @@ public final class ProductionLabel extends JComponent {
}
if (stringImage != null) {
int textOffset = coverage > stringWidth ? (coverage - stringWidth)/2 : 0;
int textOffset = width > stringWidth ? (width - stringWidth)/2 : 0;
textOffset = (textOffset >= 0) ? textOffset : 0;
g.drawImage(stringImage, textOffset,
goodsIcon.getIconHeight()/2 - stringImage.getHeight()/2, null);

View File

@ -24,6 +24,7 @@ import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
@ -31,6 +32,7 @@ import javax.swing.JComponent;
import net.sf.freecol.client.ClientOptions;
import net.sf.freecol.client.gui.Canvas;
import net.sf.freecol.common.model.AbstractGoods;
import net.sf.freecol.common.model.Goods;
import net.sf.freecol.common.model.GoodsType;
import net.sf.freecol.common.util.Utils;
@ -103,43 +105,6 @@ public final class ProductionMultiplesLabel extends JComponent {
*/
private String toolTipPrefix = null;
/**
* Creates a new <code>ProductionLabel</code> instance.
*
* @param goods a <code>Goods</code> value
* @param parent a <code>Canvas</code> value
*/
public ProductionMultiplesLabel(Goods goods, Canvas parent) {
this(goods.getType(), goods.getAmount(), -1, parent);
}
/**
* Creates a new <code>ProductionLabel</code> instance.
*
* @param goodsType an <code>int</code> value
* @param amount an <code>int</code> value
* @param parent a <code>Canvas</code> value
*/
public ProductionMultiplesLabel(GoodsType goodsType, int amount, Canvas parent) {
this(goodsType, amount, -1, parent);
}
/**
* Creates a new <code>ProductionLabel</code> instance.
*
* @param goodsType an <code>int</code> value
* @param amount an <code>int</code> value
* @param maximumProduction an <code>int</code> value
* @param parent a <code>Canvas</code> value
*/
public ProductionMultiplesLabel(GoodsType goodsType, int amount, int maximumProduction, Canvas parent) {
this( new GoodsType[]{goodsType}, new int[]{amount}, maximumProduction, parent);
}
public ProductionMultiplesLabel(GoodsType goodsType, int amount, GoodsType goodsType2, int amount2, Canvas parent) {
this( new GoodsType[]{goodsType, goodsType2}, new int[]{amount, amount2}, -1, parent);
}
/**
* Allow labels to include multiple goods.
* This is especially useful for Food.
@ -149,12 +114,10 @@ public final class ProductionMultiplesLabel extends JComponent {
* @param maximumProduction
* @param parent
*/
public ProductionMultiplesLabel(GoodsType[] goodsType, int[] amount, int maximumProduction, Canvas parent) {
public ProductionMultiplesLabel(List<AbstractGoods> goods, Canvas parent) {
super();
this.parent = parent;
this.production = amount;
this.goodsType = goodsType;
this.maximumProduction = maximumProduction;
//this.maximumProduction = maximumProduction;
ClientOptions options = parent.getClient().getClientOptions();
maxIcons = options.getInteger(ClientOptions.MAX_NUMBER_OF_GOODS_IMAGES);
displayNumber = options.getInteger(ClientOptions.MIN_NUMBER_FOR_DISPLAYING_GOODS_COUNT);
@ -162,11 +125,17 @@ public final class ProductionMultiplesLabel extends JComponent {
setFont(new Font("Dialog", Font.BOLD, 12));
totalProduction = 0;
if (goodsType != null) {
goodsIcon = new ImageIcon[goodsType.length];
for (int ii=0; ii < goodsType.length; ii++) {
goodsIcon[ii] = parent.getImageLibrary().getGoodsImageIcon(goodsType[ii]);
totalProduction += amount[ii];
if (goods != null) {
int size = goods.size();
goodsType = new GoodsType[size];
goodsIcon = new ImageIcon[size];
production = new int[size];
for (int ii=0; ii < size; ii++) {
AbstractGoods current = goods.get(ii);
goodsType[ii] = current.getType();
goodsIcon[ii] = parent.getImageLibrary().getGoodsImageIcon(current.getType());
production[ii] = current.getAmount();
totalProduction += current.getAmount();
}
compressedWidth = getMaximumIconWidth()*2;
updateToolTipText();

View File

@ -0,0 +1,109 @@
/**
* Copyright (C) 2002-2007 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.panel;
import java.awt.Dimension;
import javax.swing.JLabel;
import javax.swing.JToolTip;
import net.sf.freecol.client.gui.Canvas;
import net.sf.freecol.client.gui.i18n.Messages;
import net.sf.freecol.common.Specification;
import net.sf.freecol.common.model.Colony;
import net.sf.freecol.common.model.GoodsType;
import net.miginfocom.swing.MigLayout;
/**
* This panel provides detailed information about rebels in a colony.
*/
public class RebelToolTip extends JToolTip {
/**
* Creates this RebelToolTip.
*
* @param colony the colony for which to display information
* @param parent a <code>Canvas</code> value
*/
public RebelToolTip(Colony colony, Canvas parent) {
setLayout(new MigLayout("fillx, wrap 3", "[][right][right]", ""));
int members = colony.getMembers();
int rebels = colony.getSoL();
add(new JLabel(Messages.message("colonyPanel.rebelLabel", "%number%", "")));
add(new JLabel(Integer.toString(members)));
add(new JLabel(Integer.toString(rebels) + "%"));
add(new JLabel(Messages.message("colonyPanel.royalistLabel", "%number%", "")));
add(new JLabel(Integer.toString(colony.getUnitCount() - members)));
add(new JLabel(Integer.toString(colony.getTory()) + "%"));
int libertyProduction = 0;
for (GoodsType goodsType : Specification.getSpecification().getLibertyGoodsTypeList()) {
add(new JLabel(goodsType.getName()));
int netProduction = colony.getProductionNetOf(goodsType);
libertyProduction += netProduction;
add(new ProductionLabel(goodsType, netProduction, parent), "span 2");
}
float turns100 = 0;
float turns50 = 0;
float turnsNext = 0;
if (libertyProduction > 0) {
int liberty = colony.getLiberty();
int requiredLiberty = Colony.LIBERTY_PER_REBEL * colony.getUnitCount();
if (liberty < requiredLiberty) {
turns100 = (requiredLiberty - liberty) / libertyProduction;
}
requiredLiberty = requiredLiberty / 2;
if (liberty < requiredLiberty) {
turns50 = (requiredLiberty - liberty) / libertyProduction;
}
if (members < colony.getUnitCount()) {
requiredLiberty = Colony.LIBERTY_PER_REBEL * (members + 1);
if (liberty < requiredLiberty) {
turnsNext = (requiredLiberty - liberty) / libertyProduction;
}
}
}
String na = Messages.message("notApplicable.short");
add(new JLabel(Messages.message("report.nextMember")));
add(new JLabel(turnsNext == 0 ? na : Integer.toString((int) Math.ceil(turnsNext))), "skip");
add(new JLabel(Messages.message("report.50percent")));
add(new JLabel(turns50 == 0 ? na : Integer.toString((int) Math.ceil(turns50))), "skip");
add(new JLabel(Messages.message("report.100percent")));
add(new JLabel(turns100 == 0 ? na : Integer.toString((int) Math.ceil(turns100))), "skip");
}
public Dimension getPreferredSize() {
return new Dimension(350, 250);
}
}

View File

@ -65,7 +65,7 @@ public final class ReportColonyPanel extends ReportPanel {
// Display Panel
Collections.sort(colonies, getClient().getClientOptions().getColonyComparator());
reportPanel.setLayout(new MigLayout("fill, wrap 24", "", ""));
reportPanel.setLayout(new MigLayout("fill, wrap 16"));
for (Colony colony : colonies) {
@ -80,9 +80,9 @@ public final class ReportColonyPanel extends ReportPanel {
Collections.sort(unitList, getUnitTypeComparator());
for (Unit unit : unitList) {
UnitLabel unitLabel = new UnitLabel(unit, getCanvas(), true, true);
reportPanel.add(unitLabel, "span 2");
reportPanel.add(unitLabel, "sg units");
}
if (unitList.size() % 12 != 0) {
if (unitList.size() % 16 != 0) {
reportPanel.add(new JLabel(), "wrap");
}
@ -92,7 +92,7 @@ public final class ReportColonyPanel extends ReportPanel {
UnitLabel unitLabel = new UnitLabel(unit, getCanvas(), true, true);
reportPanel.add(unitLabel, "span 2");
}
if (unitList.size() % 12 != 0) {
if (unitList.size() % 8 != 0) {
reportPanel.add(new JLabel(), "wrap");
}
@ -102,7 +102,7 @@ public final class ReportColonyPanel extends ReportPanel {
if (netFood != 0) {
ProductionLabel productionLabel = new ProductionLabel(Goods.FOOD, netFood, getCanvas());
productionLabel.setStockNumber(colony.getFoodCount());
reportPanel.add(productionLabel, "span 3, top");
reportPanel.add(productionLabel, "span 2, top");
count++;
}
for (GoodsType goodsType : FreeCol.getSpecification().getGoodsTypeList()) {
@ -121,7 +121,7 @@ public final class ReportColonyPanel extends ReportPanel {
productionLabel.setMaxGoodsIcons(1);
}
productionLabel.setStockNumber(stockValue); // Show stored items in ReportColonyPanel
reportPanel.add(productionLabel, "span 3, top");
reportPanel.add(productionLabel, "span 2, top");
count++;
}
}
@ -136,19 +136,20 @@ public final class ReportColonyPanel extends ReportPanel {
new JLabel(new ImageIcon(ResourceManager.getImage(building.getType().getId()
+ ".image", 0.66)));
buildingLabel.setToolTipText(building.getName());
reportPanel.add(buildingLabel, "span 3");
reportPanel.add(buildingLabel, "span 2");
}
// Buildings
BuildableType currentType = colony.getCurrentlyBuilding();
JLabel buildableLabel =
new JLabel(new ImageIcon(ResourceManager.getImage(currentType.getId()
+ ".image", 0.66)));
buildableLabel.setToolTipText(Messages.message("colonyPanel.currentlyBuilding",
"%buildable%", currentType.getName()));
buildableLabel.setIcon(buildableLabel.getDisabledIcon());
reportPanel.add(buildableLabel, "span 3");
if (currentType != null) {
JLabel buildableLabel =
new JLabel(new ImageIcon(ResourceManager.getImage(currentType.getId()
+ ".image", 0.66)));
buildableLabel.setToolTipText(Messages.message("colonyPanel.currentlyBuilding",
"%buildable%", currentType.getName()));
buildableLabel.setIcon(buildableLabel.getDisabledIcon());
reportPanel.add(buildableLabel, "span 2");
}
}
}

View File

@ -58,7 +58,12 @@ public class ReportPanel extends FreeColPanel implements ActionListener {
protected JScrollPane scrollPane;
private static final Comparator<Unit> unitTypeComparator = new Comparator<Unit>() {
/**
* The saved size of this panel.
*/
private static Dimension savedSize = new Dimension(850, 600);
public static final Comparator<Unit> unitTypeComparator = new Comparator<Unit>() {
public int compare(Unit unit1, Unit unit2) {
int deltaType = unit2.getType().getIndex() - unit1.getType().getIndex();
if (deltaType == 0) {
@ -95,23 +100,30 @@ public class ReportPanel extends FreeColPanel implements ActionListener {
add(okButton, "tag ok");
setSize(850, 600);
setPreferredSize(savedSize);
}
protected Border createBorder() {
return new EmptyBorder(20, 20, 20, 20);
}
@Override
public Dimension getMinimumSize() {
return new Dimension(850, 600);
}
@Override
public Dimension getPreferredSize() {
return getMinimumSize();
/**
* Get the <code>SavedSize</code> value.
*
* @return a <code>Dimension</code> value
*/
public final Dimension getSavedSize() {
return savedSize;
}
/**
* Set the <code>SavedSize</code> value.
*
* @param newSavedSize The new SavedSize value.
*/
public final void setSavedSize(final Dimension newSavedSize) {
this.savedSize = newSavedSize;
}
/**
* Prepares this panel to be displayed.

View File

@ -25,6 +25,7 @@ import java.util.List;
import javax.swing.JButton;
import javax.swing.JTextPane;
import javax.swing.JViewport;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
@ -39,6 +40,8 @@ import net.sf.freecol.common.model.Player;
import net.sf.freecol.common.model.Unit;
import net.sf.freecol.common.model.UnitType;
import net.miginfocom.swing.MigLayout;
/**
* This panel displays the Advanced Colony Report.
*/
@ -169,6 +172,8 @@ public final class ReportRequirementsPanel extends ReportPanel {
}
// text area
int width = ((JViewport) reportPanel.getParent()).getWidth();
reportPanel.setLayout(new MigLayout("width " + width + "!"));
reportPanel.add(textPane);
}

View File

@ -22,7 +22,6 @@ package net.sf.freecol.client.gui.panel;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Arrays;
import java.util.Comparator;
@ -97,7 +96,7 @@ public final class ReportTurnPanel extends ReportPanel {
// Display Panel
reportPanel.removeAll();
reportPanel.setLayout(new MigLayout("wrap 4, fillx", "[][500!][][]", ""));
reportPanel.setLayout(new MigLayout("wrap 4", "[center][550!]:push[][]", ""));
source = this;
type = null;

View File

@ -228,9 +228,12 @@ public final class UnitLabel extends JLabel implements ActionListener {
*/
public void paintComponent(Graphics g) {
if (getToolTipText() == null) {
setToolTipText(unit.getName());
String name = unit.getName();
String equipmentLabel = unit.getEquipmentLabel();
if (equipmentLabel != null) {
name = name + " (" + equipmentLabel + ")";
}
setToolTipText(name);
if (ignoreLocation || selected || (!unit.isCarrier() && unit.getState() != UnitState.SENTRY)) {
setEnabled(true);

View File

@ -30,6 +30,7 @@ import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.border.Border;
import net.sf.freecol.client.gui.Canvas;
import net.sf.freecol.client.gui.i18n.Messages;
@ -50,6 +51,10 @@ import net.miginfocom.swing.MigLayout;
public class WorkProductionPanel extends FreeColPanel {
private static final Border border = BorderFactory
.createCompoundBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.BLACK),
BorderFactory.createEmptyBorder(2, 2, 2, 2));
public WorkProductionPanel(Canvas canvas, Unit unit) {
super(canvas);
@ -69,7 +74,6 @@ public class WorkProductionPanel extends FreeColPanel {
modifiers = sortModifiers(basicModifiers);
basicModifiers.addAll(colony.getModifierSet(goodsType.getId()));
if (colony.getProductionBonus() != 0) {
colonyModifiers.add(colony.getProductionModifier(goodsType));
modifiers.add(colony.getProductionModifier(goodsType));
}
@ -91,13 +95,16 @@ public class WorkProductionPanel extends FreeColPanel {
basicModifiers.add(building.getType().getProductionModifier());
}
if (goodsType != null) {
basicModifiers.addAll(unit.getModifierSet(goodsType.getId()));
basicModifiers.addAll(unit.getType().getModifierSet(goodsType.getId()));
}
modifiers = sortModifiers(basicModifiers);
colonyModifiers.addAll(colony.getModifierSet(goodsType.getId()));
modifiers.addAll(unit.getColony().getModifierSet(goodsType.getId()));
for (Modifier modifier : colony.getModifierSet(goodsType.getId())) {
if (modifier.getSource() != building.getType()) {
colonyModifiers.add(modifier);
}
}
modifiers.addAll(sortModifiers(colonyModifiers));
if (colony.getProductionBonus() != 0) {
colonyModifiers.add(colony.getProductionModifier(goodsType));
modifiers.add(colony.getProductionModifier(goodsType));
}
add(new JLabel(building.getName()), "span, align center, wrap 30");
@ -107,6 +114,7 @@ public class WorkProductionPanel extends FreeColPanel {
add(new UnitLabel(unit, canvas, false, false), "wrap");
int totalPercentage = 0;
for (Modifier modifier : modifiers) {
FreeColGameObjectType source = modifier.getSource();
String sourceName;
@ -122,7 +130,6 @@ public class WorkProductionPanel extends FreeColPanel {
}
}
}
add(new JLabel(sourceName), "newline");
String bonus = getModifierFormat().format(modifier.getValue());
boolean percentage = false;
switch(modifier.getType()) {
@ -141,7 +148,21 @@ public class WorkProductionPanel extends FreeColPanel {
bonus = "\u00D7" + bonus;
break;
default:
}
}
if (modifier.getType() == Modifier.Type.PERCENTAGE) {
totalPercentage += modifier.getValue();
} else if (totalPercentage != 0) {
String result = getModifierFormat().format(totalPercentage);
if (totalPercentage > 0) {
result = "+" + result;
}
JLabel resultLabel = new JLabel(result);
resultLabel.setBorder(border);
add(resultLabel, "skip");
add(new JLabel("%"));
totalPercentage = 0;
}
add(new JLabel(sourceName), "newline");
add(new JLabel(bonus));
if (percentage) {
add(new JLabel("%"));
@ -150,17 +171,17 @@ public class WorkProductionPanel extends FreeColPanel {
Font bigFont = getFont().deriveFont(Font.BOLD, 16);
int result = (int) (FeatureContainer.applyModifierSet(0, getGame().getTurn(), basicModifiers)
+ FeatureContainer.applyModifierSet(0, getGame().getTurn(), colonyModifiers));
int result = (int) FeatureContainer.applyModifierSet(0, getGame().getTurn(), basicModifiers);
result = (int) FeatureContainer.applyModifierSet(result, getGame().getTurn(), colonyModifiers);
result += colony.getProductionBonus();
JLabel finalLabel = new JLabel(Messages.message("model.source.finalResult.name"));
finalLabel.setFont(bigFont);
add(finalLabel, "newline");
JLabel finalResult = new JLabel(getModifierFormat().format(result));
finalResult.setFont(bigFont);
finalResult.setBorder(BorderFactory
.createCompoundBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.BLACK),
BorderFactory.createEmptyBorder(2, 2, 2, 2)));
finalResult.setBorder(border);
add(finalResult, "wrap 30");
add(okButton, "span, tag ok");

View File

@ -229,13 +229,7 @@ public abstract class Feature extends FreeColObject {
return true;
} else if (o instanceof Feature) {
Feature feature = (Feature) o;
if (getId() == null) {
if (feature.getId() != null) {
return false;
}
} else if (feature.getId() == null) {
return false;
} else if (!getId().equals(feature.getId())) {
if (getId() != feature.getId()) {
return false;
}
if (source != feature.source) {

View File

@ -530,14 +530,14 @@ abstract public class Settlement extends FreeColGameObject implements Location,
* Gets food consumption by type
*/
public int getFoodConsumptionByType(GoodsType type) {
// Since for now only model.goods.food are needed for other purposes
//we will hard code the preference of consumption for other types of food
// If later other requirements appear, an allocation algorithm needs to be
//implemented
// Since for now only model.goods.food are needed for other
// purposes we will hard code the preference of consumption
// for other types of food If later other requirements appear,
// an allocation algorithm needs to be implemented
if(!type.isFoodType()){
logger.warning("Good type given isnt food type");
return 0;
logger.warning("Good type given isnt food type");
return 0;
}
int required = getFoodConsumption();
@ -545,16 +545,16 @@ abstract public class Settlement extends FreeColGameObject implements Location,
GoodsType corn = FreeCol.getSpecification().getGoodsType("model.goods.food");
for (GoodsType foodType : FreeCol.getSpecification().getGoodsFood()) {
if(foodType == corn){
// consumption of corn calculated last
continue;
}
if(foodType == corn){
// consumption of corn calculated last
continue;
}
consumed = Math.min(getProductionOf(foodType),required);
if(type == foodType){
return consumed;
}
required -= consumed;
consumed = Math.min(getProductionOf(foodType),required);
if(type == foodType){
return consumed;
}
required -= consumed;
}
// type asked is corn, calculate consumption and return

View File

@ -709,17 +709,19 @@ public class SimpleCombatModel implements CombatModel {
// the attacker is Indian, which cannot be a player
// only messages directed to the losing player need to be sent
if (colony.getUnitCount() <= 1) {
defendingPlayer.getHistory().add(new HistoryEvent(defendingPlayer.getGame().getTurn().getNumber(),
HistoryEvent.Type.COLONY_DESTROYED,
"%nation%", defendingPlayer.getNationAsString(),
"%colony%", colony.getName()));
defendingPlayer.addModelMessage(defendingPlayer,
ModelMessage.MessageType.COMBAT_RESULT,
"model.unit.colonyBurning",
"%colony%", colony.getName(),
"%amount%", Integer.toString(plunderGold),
"%nation%", attackingPlayer.getNationAsString(),
"%unit%", attacker.getName());
defendingPlayer.getHistory()
.add(new HistoryEvent(defendingPlayer.getGame().getTurn().getNumber(),
HistoryEvent.Type.COLONY_DESTROYED,
"%nation%", attackingPlayer.getNationAsString(),
"%colony%", colony.getName()));
defendingPlayer
.addModelMessage(defendingPlayer,
ModelMessage.MessageType.COMBAT_RESULT,
"model.unit.colonyBurning",
"%colony%", colony.getName(),
"%amount%", Integer.toString(plunderGold),
"%nation%", attackingPlayer.getNationAsString(),
"%unit%", attacker.getName());
attackingPlayer.modifyGold(plunderGold);
defendingPlayer.modifyGold(-plunderGold);
damageAllShips(colony, attacker, repairLocation);

View File

@ -2457,6 +2457,36 @@ public class Unit extends FreeColGameObject implements Locatable, Location, Owna
return completeName;
}
/**
* Return a description of the unit's equipment.
*
* @return a <code>String</code> value
*/
public String getEquipmentLabel() {
if (equipment != null && !equipment.isEmpty()) {
List<String> equipmentStrings = new ArrayList<String>();
for (java.util.Map.Entry<EquipmentType, Integer> entry : equipment.getValues().entrySet()) {
EquipmentType type = entry.getKey();
int amount = entry.getValue().intValue();
if (type.getGoodsRequired().isEmpty()) {
equipmentStrings.add(Messages.message("model.goods.goodsAmount",
"%goods%", type.getName(),
"%amount%", Integer.toString(amount)));
} else {
for (AbstractGoods goods : type.getGoodsRequired()) {
equipmentStrings.add(Messages.message("model.goods.goodsAmount",
"%goods%", goods.getType().getName(),
"%amount%", Integer.toString(amount * goods.getAmount())));
}
}
}
return Utils.join("/", equipmentStrings.toArray(new String[equipmentStrings.size()]));
} else {
return null;
}
}
/**
* Returns the name of a unit in a human readable format. The return value
* can be used when communicating with the user.

View File

@ -58,7 +58,9 @@ public class LanguageOption extends AbstractOption {
{"arz", "\u0645\u0635\u0631\u064A"},
{"hsb", "Serb\u0161\u0107ina"},
{"nds", "Plattd\u00fc\u00fctsch"},
{"pms", "Piemont\u00e9s"}
{"pms", "Piemont\u00e9s"},
{"be-tarask", "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f "
+ "(\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)" }
};

View File

@ -1028,6 +1028,14 @@ public final class InGameInputHandler extends InputHandler implements NetworkCon
defendingPlayer.surrenderTo(player);
}
// We need to send an update of the unit, may have been changed
//like getting cargo
if (result.type.compareTo(CombatResultType.WIN) >= 0 && unit.isNaval()){
Element update = reply.getOwnerDocument().createElement("update");
update.appendChild(unit.toXMLElement(player,update.getOwnerDocument()));
reply.appendChild(update);
}
if (result.type.compareTo(CombatResultType.WIN) >= 0
&& unit.getTile() != newTile
&& oldUnits < unit.getTile().getUnitCount()) {

View File

@ -395,15 +395,76 @@ public class BuildingTest extends FreeColTestCase {
game.setMap(getTestMap(plainsType,true));
Colony colony = getStandardColony(6);
Unit unit = colony.getRandomUnit();
Building building = colony.getBuilding(spec().getBuildingType("model.building.TownHall"));
int bellProduction = building.getProduction();
int expectBellProd = 1;
assertEquals("Wrong initial bell production",expectBellProd,bellProduction);
building.add(unit);
bellProduction = building.getProduction();
expectBellProd = 4; // 1 initial plus 3 from the colonist
assertEquals("Wrong bell production",expectBellProd,bellProduction);
Player owner = colony.getOwner();
Unit unit1 = colony.getUnitList().get(0);
Unit unit2 = colony.getUnitList().get(1);
BuildingType townHall = spec().getBuildingType("model.building.TownHall");
Building building = colony.getBuilding(townHall);
Set<Modifier> modifiers = colony.getModifierSet("model.goods.bells");
assertEquals(1, modifiers.size());
Modifier bellsModifier = modifiers.iterator().next();
assertEquals(Modifier.Type.ADDITIVE, bellsModifier.getType());
assertEquals(1.0f, bellsModifier.getValue());
assertEquals("Wrong initial bell production",
(int) bellsModifier.getValue(), building.getProduction());
building.add(unit1);
// 3 from the colonist
assertEquals(3, unit1.getProductionOf(Goods.BELLS, townHall.getBasicProduction()));
assertEquals(3, building.getUnitProductivity(unit1));
// 3 from the colonist + 1
assertEquals("Wrong bell production", 4, building.getProduction());
owner.addFather(spec().getFoundingFather("model.foundingFather.thomasJefferson"));
// 3 from the colonist + 50% = 5
assertEquals(5, unit1.getProductionOf(Goods.BELLS, townHall.getBasicProduction()));
assertEquals(5, building.getUnitProductivity(unit1));
// 3 from the colonist + 50% + 1 = 6
assertEquals("Wrong bell production with Jefferson", 6, building.getProduction());
building.add(unit2);
// 3 from each colonist + 50% = 5
assertEquals(5, unit1.getProductionOf(Goods.BELLS, townHall.getBasicProduction()));
assertEquals(5, building.getUnitProductivity(unit1));
assertEquals(5, unit2.getProductionOf(Goods.BELLS, townHall.getBasicProduction()));
assertEquals(5, building.getUnitProductivity(unit2));
// 5 + 5 + 1 = 11
assertEquals("Wrong bell production with Jefferson", 11, building.getProduction());
setProductionBonus(colony, 2);
// 3 from each colonist + 50% + 2 = 7
assertEquals(5, unit1.getProductionOf(Goods.BELLS, townHall.getBasicProduction()));
assertEquals(7, building.getUnitProductivity(unit1));
assertEquals(5, unit2.getProductionOf(Goods.BELLS, townHall.getBasicProduction()));
assertEquals(7, building.getUnitProductivity(unit2));
// 7 + 7 + 1 = 15
assertEquals("Wrong bell production with Jefferson and +2 production bonus",
15, building.getProduction());
Building newspaper = new Building(getGame(), colony, newspaperType);
colony.addBuilding(newspaper);
System.out.println("unit");
for (Modifier modifier : unit1.getModifierSet("model.goods.bells")) {
System.out.println(modifier);
}
System.out.println("colony");
for (Modifier modifier : colony.getModifierSet("model.goods.bells")) {
System.out.println(modifier);
}
// 3 from each colonist + 50% + 2 = 7
assertEquals(5, unit1.getProductionOf(Goods.BELLS, townHall.getBasicProduction()));
assertEquals(7, building.getUnitProductivity(unit1));
assertEquals(5, unit2.getProductionOf(Goods.BELLS, townHall.getBasicProduction()));
assertEquals(7, building.getUnitProductivity(unit2));
// 7 + 7 + 1 + 150% = 38
assertEquals("Wrong bell production with Jefferson, newspaper and +2 production bonus",
38, building.getProduction());
}
public void testPrintingPressBonus() {

View File

@ -19,8 +19,6 @@
package net.sf.freecol.common.model;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -94,16 +92,6 @@ public class SchoolTest extends FreeColTestCase {
return colony.getBuilding(schoolType);
}
private void setProductionBonus(Colony colony, int value) {
try {
Field productionBonus = Colony.class.getDeclaredField("productionBonus");
productionBonus.setAccessible(true);
productionBonus.setInt(colony, value);
} catch (Exception e) {
// do nothing
}
}
BuildingType schoolType = spec().getBuildingType("model.building.Schoolhouse");

View File

@ -19,6 +19,8 @@
package net.sf.freecol.util.test;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
import java.util.Locale;
@ -523,4 +525,23 @@ public class FreeColTestCase extends TestCase {
return this;
}
}
/**
* Set the production bonus of the given colony to the given
* value.
*
* @param colony a <code>Colony</code> value
* @param value an <code>int</code> value
*/
public void setProductionBonus(Colony colony, int value) {
try {
Field productionBonus = Colony.class.getDeclaredField("productionBonus");
productionBonus.setAccessible(true);
productionBonus.setInt(colony, value);
} catch (Exception e) {
// do nothing
}
}
}