/**
*
*/
package logbook.gui;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import logbook.dto.ResultRank;
import logbook.gui.logic.GuiUpdator;
import logbook.gui.logic.IntegerPair;
import logbook.gui.logic.LayoutLogic;
import logbook.internal.BattleResultFilter;
import logbook.internal.BattleResultServer;
import logbook.internal.TimeSpanKind;
import logbook.util.ReportUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
/**
* @author Nekopanda
*
*/
public class BattleFilterDialog extends WindowBase {
private static final String ALL_RANKS = "SABCDE";
private static final String SELECT_RANK = "SELECT";
private final DropReportTable parent;
private List<IntegerPair> mapList;
private CheckAndCombo mapCombo;
private List<Integer> cellList;
private CheckAndCombo cellCombo;
private List<String> shipList;
private CheckAndCombo shipCombo;
private List<String> rankList;
private CheckAndCombo rankCombo;
private List<Boolean> kindList;
private CheckAndCombo kindCombo;
private List<TimeSpanKind> timeList;
private CheckAndCombo timeCombo;
private LabelAndCalender fromDate;
private LabelAndCalender toDate;
private Composite rankCompo;
private Label rankPlaceholder;
private List<Button> rankCheckboxList;
public BattleFilterDialog(DropReportTable parent) {
super.createContents(parent, SWT.CLOSE | SWT.TITLE | SWT.RESIZE, false);
this.parent = parent;
}
/**
* Open the dialog.
*/
@Override
public void open() {
if (!this.isWindowInitialized()) {
this.createContents();
this.registerEvents();
// 閉じたときに dispose しない
this.getShell().addShellListener(new ShellAdapter() {
@Override
public void shellClosed(ShellEvent e) {
e.doit = false;
BattleFilterDialog.this.setVisible(false);
}
});
this.setWindowInitialized(true);
}
this.updateContents();
if (this.getVisible() == false) {
this.getShell().pack();
this.setVisible(true);
}
this.getShell().setActive();
return;
}
/**
* Create contents of the dialog.
*/
private void createContents() {
Shell shell = this.getShell();
shell.setText("フィルター");
GridLayout glShell = new GridLayout(5, false);
shell.setLayout(glShell);
SelectionListener listener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
BattleFilterDialog.this.updateCalenderVisible();
BattleFilterDialog.this.updateRankCheckboxVisible();
BattleFilterDialog.this.parent.updateFilter(BattleFilterDialog.this.createFilter());
}
};
// マップ
this.mapCombo = new CheckAndCombo(shell, "マップ", 1);
this.mapCombo.initState(listener);
// セル
this.cellCombo = new CheckAndCombo(shell, "マス", 1);
this.cellCombo.initState(listener);
// ランクチェックボックス
this.rankCompo = new Composite(shell, SWT.NONE);
this.rankCompo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 5));
RowLayout rankCompoLayout = new RowLayout(SWT.VERTICAL);
rankCompoLayout.wrap = false;
this.rankCompo.setLayout(rankCompoLayout);
this.rankCheckboxList = new ArrayList<Button>();
for (char rank : ALL_RANKS.toCharArray()) {
Button checkbox = new Button(this.rankCompo, SWT.CHECK);
this.rankCheckboxList.add(checkbox);
checkbox.setText(String.valueOf(rank));
checkbox.setData(rank);
checkbox.addSelectionListener(listener);
}
this.rankPlaceholder = new Label(shell, SWT.NONE);
this.rankPlaceholder.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 5));
// ドロップ艦
this.shipCombo = new CheckAndCombo(shell, "ドロップ", 1);
this.shipCombo.initState(listener);
// ランク
this.rankList = new ArrayList<String>();
for (char rank : ALL_RANKS.toCharArray()) {
this.rankList.add(String.valueOf(rank));
}
this.rankList.add("SAB");
this.rankList.add("CDE");
this.rankList.add(SELECT_RANK);
this.rankCombo = new CheckAndCombo(shell, "ランク", 1);
for (String rankString : this.rankList) {
if (rankString.length() == 1) {
this.rankCombo.combo.add(ResultRank.fromRank(rankString).toString());
}
else {
break;
}
}
this.rankCombo.combo.add("勝利(S,A,B)");
this.rankCombo.combo.add("敗北(C,D,E)");
this.rankCombo.combo.add("右から選択");
this.rankCombo.initState(listener);
// 戦闘種別
this.kindList = new ArrayList<Boolean>();
this.kindCombo = new CheckAndCombo(shell, "戦闘種別", 1);
this.kindCombo.combo.add("出撃のみ");
this.kindList.add(false);
this.kindCombo.combo.add("演習のみ");
this.kindList.add(true);
this.kindCombo.initState(listener);
// 期間
this.timeList = new ArrayList<TimeSpanKind>();
this.timeCombo = new CheckAndCombo(shell, "期間", 1);
for (TimeSpanKind time : TimeSpanKind.values()) {
this.timeCombo.combo.add(time.toString());
this.timeList.add(time);
}
this.timeCombo.initState(listener);
// 時刻
Label startLabel = new Label(shell, SWT.NONE);
Label endLabel = new Label(shell, SWT.NONE);
this.fromDate = new LabelAndCalender(shell, startLabel, "開始", 2);
this.toDate = new LabelAndCalender(shell, endLabel, "終了", 2);
this.fromDate.initState(listener, BattleResultServer.get().getFirstBattleTime());
this.toDate.initState(listener, BattleResultServer.get().getLastBattleTime());
// 初期値
BattleResultFilter filter = this.parent.getFilter();
if (filter != null) {
int mapIdx = (filter.map == null) ? -1 : this.mapList.indexOf(filter.map);
int cellIdx = (filter.cell == null) ? -1 : this.cellList.indexOf(filter.cell);
int dtopShipIdx = (filter.dropShip == null) ? -1 : this.shipList.indexOf(filter.dropShip);
int rankIdx = -1;
if ((filter.rankCombo != null) && (filter.rankCombo.length() == 1)) {
rankIdx = this.rankList.indexOf(filter.rankCombo);
if (rankIdx == -1) {
rankIdx = this.rankList.indexOf(SELECT_RANK);
}
}
int kindIdx =
(filter.printPractice == null) ? -1 :
filter.printPractice ? 1 : 0;
int timeSpanIdx = (filter.timeSpan == null) ? -1 : this.timeList.indexOf(filter.timeSpan);
if (mapIdx != -1) {
this.mapCombo.select(mapIdx);
}
if (cellIdx != -1) {
this.cellCombo.select(cellIdx);
}
if (dtopShipIdx != -1) {
this.shipCombo.select(dtopShipIdx);
}
if (rankIdx != -1) {
this.rankCombo.select(rankIdx);
}
if (kindIdx != -1) {
this.kindCombo.select(kindIdx);
}
if (timeSpanIdx != -1) {
this.timeCombo.select(timeSpanIdx);
}
if (filter.fromTime != null) {
this.fromDate.setDate(toCalendar(filter.fromTime), false);
}
if (filter.toTime != null) {
this.toDate.setDate(toCalendar(filter.toTime), true);
}
}
this.updateCalenderVisible();
this.updateRankCheckboxVisible();
shell.pack();
// データの更新を受け取る
final Runnable datalistener = new GuiUpdator(new Runnable() {
@Override
public void run() {
BattleFilterDialog.this.updateContents();
}
});
BattleResultServer.addListener(datalistener);
this.getShell().addListener(SWT.Dispose, new Listener() {
@Override
public void handleEvent(Event event) {
BattleResultServer.removeListener(datalistener);
}
});
}
private void updateContents() {
// マップ
this.mapList = BattleResultServer.get().getMapList();
this.mapCombo.updateContents(this.mapList);
// セル
this.cellList = BattleResultServer.get().getCellList();
this.cellCombo.updateContents(this.cellList);
// ドロップ艦
this.shipList = BattleResultServer.get().getDropShipList();
this.shipCombo.updateContents(this.shipList);
}
private static Calendar toCalendar(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar;
}
private BattleResultFilter createFilter() {
BattleResultFilter filter = this.parent.getFilter();
if (filter == null) {
filter = new BattleResultFilter();
}
filter.map = (IntegerPair) getSelectedItem(this.mapCombo, this.mapList);
filter.cell = (Integer) getSelectedItem(this.cellCombo, this.cellList);
filter.dropShip = (String) getSelectedItem(this.shipCombo, this.shipList);
filter.rankCombo = (String) getSelectedItem(this.rankCombo, this.rankList);
if ((filter.rankCombo != null) && filter.rankCombo.equals(SELECT_RANK)) {
filter.rankCombo = "";
for (Button check : this.rankCheckboxList) {
if (check.getSelection()) {
Character rank = (Character) check.getData();
filter.rankCombo += rank;
}
}
}
filter.printPractice = (Boolean) getSelectedItem(this.kindCombo, this.kindList);
TimeSpanKind timeSpan = (TimeSpanKind) getSelectedItem(this.timeCombo, this.timeList);
if (timeSpan == TimeSpanKind.MANUAL) {
filter.timeSpan = null;
filter.fromTime = this.fromDate.getSelectedDate(false);
filter.toTime = this.toDate.getSelectedDate(true);
}
else {
filter.timeSpan = timeSpan;
filter.fromTime = null;
filter.toTime = null;
}
return filter;
}
private static Object getSelectedItem(CheckAndCombo combo, List<?> data) {
if (combo.button.getSelection()) {
int idx = combo.combo.getSelectionIndex();
if ((idx >= 0) && (idx < data.size())) {
return data.get(idx);
}
}
return null;
}
private void updateCalenderVisible() {
TimeSpanKind timeSpan = (TimeSpanKind) getSelectedItem(this.timeCombo, this.timeList);
boolean isManual = (timeSpan == TimeSpanKind.MANUAL);
if (isManual ^ this.fromDate.getVisible()) {
this.fromDate.setVisible(isManual);
this.toDate.setVisible(isManual);
if (isManual) {
this.getShell().pack();
}
}
}
private void updateRankCheckboxVisible() {
String selected = (String) getSelectedItem(this.rankCombo, this.rankList);
boolean isSelect = ((selected != null) && selected.equals(SELECT_RANK));
if (isSelect ^ this.rankCompo.getVisible()) {
LayoutLogic.hide(this.rankCompo, !isSelect);
LayoutLogic.hide(this.rankPlaceholder, isSelect);
if (isSelect) {
this.getShell().pack();
}
}
}
/**
* 選択した時にコンボボックスを制御する
*/
private static class CheckAdapter extends SelectionAdapter {
final Button button;
final Composite composite;
public CheckAdapter(Button button, Composite composite) {
this.button = button;
this.composite = composite;
button.addSelectionListener(this);
}
@Override
public void widgetSelected(SelectionEvent e) {
this.composite.setEnabled(this.button.getSelection());
}
}
private static class CheckAndCombo extends CheckAdapter {
final Combo combo;
public CheckAndCombo(Shell shell, String text, int comboSpan) {
super(new Button(shell, SWT.CHECK), new Combo(shell, SWT.READ_ONLY));
GridData data = new GridData(GridData.FILL_HORIZONTAL);
data.horizontalSpan = comboSpan;
this.composite.setLayoutData(data);
this.button.setText(text);
this.combo = (Combo) this.composite;
this.combo.setEnabled(false);
}
public void select(int idx) {
this.button.setSelection(true);
this.combo.setEnabled(true);
this.combo.select(idx);
}
public void initState(SelectionListener listener) {
this.button.addSelectionListener(listener);
this.combo.addSelectionListener(listener);
this.combo.select(0);
}
public void updateContents(List<?> items) {
int prevSelection = this.combo.getSelectionIndex();
this.combo.removeAll();
for (Object item : items) {
this.combo.add(item.toString());
}
this.combo.select(prevSelection);
}
}
private static class LabelAndCalender {
final DateTime datetime;
final Label label;
boolean visible;
public LabelAndCalender(Shell shell, Label label, String text, int comboSpan) {
this.label = label;
this.datetime = new DateTime(shell, SWT.CALENDAR);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
data.horizontalSpan = comboSpan;
data.horizontalAlignment = SWT.CENTER;
this.label.setLayoutData(data);
GridData data2 = new GridData(GridData.FILL_HORIZONTAL);
data2.horizontalSpan = comboSpan;
this.datetime.setLayoutData(data2);
this.label.setText(text);
this.visible = true;
}
public void setDate(Calendar calendar, boolean endOfDay) {
this.datetime.setYear(calendar.get(Calendar.YEAR));
this.datetime.setMonth(calendar.get(Calendar.MONTH));
int day = calendar.get(Calendar.DAY_OF_MONTH);
this.datetime.setDay(endOfDay ? (day - 1) : day);
}
public Date getSelectedDate(boolean endOfDay) {
int year = this.datetime.getYear();
int month = this.datetime.getMonth();
int day = this.datetime.getDay();
Calendar cal = Calendar.getInstance();
cal.set(year, month, endOfDay ? (day + 1) : day, 0, 0, 0);
return cal.getTime();
}
public void setVisible(boolean visible) {
if (this.visible != visible) {
this.visible = visible;
LayoutLogic.hide(this.label, !visible);
LayoutLogic.hide(this.datetime, !visible);
}
}
public boolean getVisible() {
return this.visible;
}
public void initState(SelectionListener listener, Date date) {
this.datetime.addSelectionListener(listener);
this.setDate(ReportUtils.calendarFromDate(date), false);
}
}
}