package logbook.gui.widgets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import logbook.config.ShipGroupConfig;
import logbook.config.bean.ShipGroupBean;
import logbook.constants.AppConstants;
import logbook.data.context.GlobalContext;
import logbook.dto.ItemDto;
import logbook.dto.ShipFilterDto;
import logbook.gui.ShipTable;
import logbook.gui.WindowBase;
import logbook.gui.logic.LayoutLogic;
import logbook.gui.logic.ShipGroupListener;
import logbook.gui.logic.ShipGroupObserver;
import logbook.internal.MasterData;
import logbook.util.SwtUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.RowData;
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.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.wb.swt.SWTResourceManager;
/**
* 所有艦娘一覧で使用するフィルターダイアログ
*
*/
public final class ShipFilterComposite extends Composite {
private final ShipTable shipTable;
/** 変更イベントを発生させるか? */
private boolean changeEnabled = false;
private boolean panelVisible = true;
private boolean etcVisible = true;
private int groupMode = 0;
private Menu switchMenu;
private MenuItem groupMenuItem;
private MenuItem typeMenuItem;
private MenuItem etcMenuItem;
private Composite switchCompo;
private Composite groupCompo;
private Button groupAllButton;
private final List<Button> groupButtons = new ArrayList<>();
private ShipGroupBean selectedGroup;
private Composite typeCompo;
private Composite typeCheckCompo;
private final Map<Integer, Button> typeButtons = new TreeMap<>();
private int maxTypeId;
private Composite etcCompo;
/** 名前 */
private Combo nametext;
/** 名前.正規表現を使用する */
private Button regexp;
/** 全て選択 */
private Button selectall;
private Composite lockedGroup;
/** 鍵付き */
private Button lockedAny;
/** 鍵付き */
private Button lockedOnly;
/** 鍵付きではない */
private Button lockedNo;
private Composite fleetGroup;
/** 艦隊所属 */
private Button fleetAny;
/** 艦隊所属 */
private Button fleetOnly;
/** 艦隊所属でない */
private Button fleetNo;
/** 遠征中を除外 */
public Button ignoreOnMission;
/** 要修理 */
public Button needBath;
/**
* Create the dialog.
*
* @param shipTable 呼び出し元
*/
public ShipFilterComposite(ShipTable shipTable) {
super(shipTable.getShell(), SWT.NONE);
this.shipTable = shipTable;
this.createContents();
}
/**
* Create contents of the dialog.
*/
private void createContents() {
// ただ反映するだけ
SelectionListener listener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (ShipFilterComposite.this.changeEnabled) {
ShipFilterComposite.this.shipTable.updateFilter(ShipFilterComposite.this.createFilter(), true);
}
}
};
SelectionListener groupListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ShipFilterComposite.this.groupButtonSelected((Button) e.getSource(), null);
}
};
this.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
this.setLayout(SwtUtils.makeGridLayout(2, 0, 0, 0, 0));
this.switchCompo = new Composite(this, SWT.NONE);
this.switchCompo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
this.switchCompo.setLayout(SwtUtils.makeGridLayout(1, 0, 0, 0, 0));
// グループタブ
this.groupCompo = new Composite(this.switchCompo, SWT.BORDER);
this.groupCompo.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, true, false, 1, 1));
this.groupCompo.setLayout(SwtUtils.makeRowLayout(true, 0, 0, true));
this.groupAllButton = new Button(this.groupCompo, SWT.RADIO);
this.groupAllButton.setText("すべて");
this.groupAllButton.addSelectionListener(groupListener);
// 艦種タブ
this.typeCompo = new Composite(this.switchCompo, SWT.NONE);
this.typeCompo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
this.typeCompo.setLayout(SwtUtils.makeGridLayout(1, 0, 0, 0, 0));
// 艦種カテゴリボタン
this.typeCheckCompo = new Composite(this.typeCompo, SWT.NONE);
this.typeCheckCompo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
this.typeCheckCompo.setLayout(SwtUtils.makeRowLayout(true, 1, 0, true));
this.selectall = new Button(this.typeCheckCompo, SWT.CHECK);
this.selectall.setText("全て選択");
this.selectall.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
boolean select = ShipFilterComposite.this.selectall.getSelection();
for (Button button : ShipFilterComposite.this.typeButtons.values()) {
button.setSelection(select);
}
if (ShipFilterComposite.this.changeEnabled) {
ShipFilterComposite.this.shipTable.updateFilter(ShipFilterComposite.this.createFilter(), true);
}
}
});
Composite typeSelectorCompo = new Composite(this.typeCompo, SWT.NONE);
typeSelectorCompo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
typeSelectorCompo.setLayout(new RowLayout(SWT.HORIZONTAL));
SelectionListener categoryListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ShipFilterComposite.this.categoryButtonSelected((Button) e.getSource());
}
};
String[] categoryNames = AppConstants.SHIP_CATEGORY_NAMES;
int[][] categoryTypes = AppConstants.SHIP_CATEGORY_TYPES;
for (int i = 0; i < categoryNames.length; ++i) {
Button button = new Button(typeSelectorCompo, SWT.NONE);
button.setText(categoryNames[i]);
button.setData(categoryTypes[i]);
button.addSelectionListener(categoryListener);
}
// その他パネル
this.etcCompo = new Composite(this.switchCompo, SWT.NONE);
this.etcCompo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
this.etcCompo.setLayout(SwtUtils.makeGridLayout(2, 0, 0, 0, 0));
Composite etcSelectCompo = new Composite(this.etcCompo, SWT.NONE);
etcSelectCompo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
etcSelectCompo.setLayout(SwtUtils.makeRowLayout(true, 2, 0, true));
{
this.lockedGroup = new Composite(etcSelectCompo, SWT.BORDER);
this.lockedGroup.setLayout(SwtUtils.makeRowLayout(true, 0, 0, false));
this.lockedAny = new Button(this.lockedGroup, SWT.RADIO);
this.lockedAny.setText("すべて");
this.lockedAny.addSelectionListener(listener);
this.lockedOnly = new Button(this.lockedGroup, SWT.RADIO);
this.lockedOnly.setText("鍵付き");
this.lockedOnly.addSelectionListener(listener);
this.lockedNo = new Button(this.lockedGroup, SWT.RADIO);
this.lockedNo.setText("鍵付きでない");
this.lockedNo.addSelectionListener(listener);
}
{
this.fleetGroup = new Composite(etcSelectCompo, SWT.BORDER);
this.fleetGroup.setLayout(SwtUtils.makeRowLayout(true, 0, 0, false));
this.fleetAny = new Button(this.fleetGroup, SWT.RADIO);
this.fleetAny.setText("すべて");
this.fleetAny.addSelectionListener(listener);
this.fleetOnly = new Button(this.fleetGroup, SWT.RADIO);
this.fleetOnly.setText("艦隊所属");
this.fleetOnly.addSelectionListener(listener);
this.fleetNo = new Button(this.fleetGroup, SWT.RADIO);
this.fleetNo.setText("艦隊所属でない");
this.fleetNo.addSelectionListener(listener);
}
this.ignoreOnMission = new Button(etcSelectCompo, SWT.CHECK);
this.ignoreOnMission.setText("遠征中を除外");
this.ignoreOnMission.setSelection(false);
this.ignoreOnMission.addSelectionListener(listener);
this.needBath = new Button(etcSelectCompo, SWT.CHECK);
this.needBath.setText("お風呂に入りたい艦娘");
this.needBath.setSelection(false);
this.needBath.addSelectionListener(listener);
//----------- フリーワード
Composite namegroup = new Composite(this.etcCompo, SWT.NONE);
namegroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
namegroup.setLayout(new RowLayout(SWT.HORIZONTAL));
this.nametext = new Combo(namegroup, SWT.BORDER);
this.nametext.setLayoutData(new RowData(150, SWT.DEFAULT));
this.nametext.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
if (ShipFilterComposite.this.changeEnabled)
ShipFilterComposite.this.shipTable.updateFilter(ShipFilterComposite.this.createFilter(), false);
}
});
this.nametext.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
// 装備から選択された場合は正規表現をオフ
ShipFilterComposite.this.regexp.setSelection(false);
}
});
this.nametext.setToolTipText("フリーワード検索(半角SPでAND検索)");
this.regexp = new Button(namegroup, SWT.CHECK);
this.regexp.setToolTipText("正規表現:オフ");
this.regexp.addSelectionListener(listener);
this.regexp.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Button button = (Button) e.widget;
String tooltip = "正規表現:" + (button.getSelection() ? "オン" : "オフ");
button.setToolTipText(tooltip);
}
});
//-----------------------------
//------------------ 切り替えボタン
SelectionListener arrowButtonListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int next = (ShipFilterComposite.this.groupMode + 1) % 3;
ShipFilterComposite.this.setGroupMode(next);
//ShipFilterComposite.this.shipTable.getFilterMenu().setGroupMode(ShipFilterComposite.this.groupMode);
ShipFilterComposite.this.shipTable.updateFilter(ShipFilterComposite.this.createFilter(), true);
ShipFilterComposite.this.shipTable.getShell().layout();
}
};
Button btnRight = new Button(this, SWT.NONE);
GridData gdBtnRight = new GridData(SWT.FILL, SWT.TOP, false, false, 1, 1);
gdBtnRight.widthHint = SwtUtils.DPIAwareWidth(24);
gdBtnRight.heightHint = SwtUtils.DPIAwareHeight(24);
btnRight.setLayoutData(gdBtnRight);
btnRight.addSelectionListener(arrowButtonListener);
SwtUtils.setButtonImage(btnRight, SWTResourceManager.getImage(WindowBase.class, AppConstants.R_ICON_RIGHT));
//------------------
this.switchMenu = new Menu(this);
SelectionListener switchSelectionListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ShipFilterComposite.this.switchMenuSelected(e);
}
};
this.groupMenuItem = new MenuItem(this.switchMenu, SWT.CHECK);
this.groupMenuItem.setText("グループ");
this.groupMenuItem.setSelection(true);
this.groupMenuItem.addSelectionListener(switchSelectionListener);
this.typeMenuItem = new MenuItem(this.switchMenu, SWT.CHECK);
this.typeMenuItem.setText("艦種");
this.typeMenuItem.addSelectionListener(switchSelectionListener);
// セパレータ
new MenuItem(this.switchMenu, SWT.SEPARATOR);
this.etcMenuItem = new MenuItem(this.switchMenu, SWT.CHECK);
this.etcMenuItem.setText("その他");
this.etcMenuItem.setSelection(true);
this.etcMenuItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
boolean panelVisible = ShipFilterComposite.this.panelVisible;
boolean etcVisible = ShipFilterComposite.this.etcMenuItem.getSelection();
ShipFilterComposite.this.setPanelVisible(panelVisible, etcVisible);
ShipFilterComposite.this.shipTable.getFilterMenu().setPanelVisible(panelVisible, etcVisible);
ShipFilterComposite.this.shipTable.getShell().layout();
}
});
setMenu(this, this.switchMenu);
this.setData("disable-window-menu", new Object());
this.switchPanel();
final ShipGroupListener shipGroupListner = new ShipGroupListener() {
@Override
public void listChanged() {
ShipFilterComposite.this.setRedraw(false);
ShipFilterComposite.this.recreateGroupButtons();
ShipFilterComposite.this.groupCompo.layout();
ShipFilterComposite.this.setRedraw(true);
}
@Override
public void groupNameChanged(ShipGroupBean group) {
int idx = ShipGroupConfig.get().getGroup().indexOf(group);
if (idx != -1) {
ShipFilterComposite.this.groupButtons.get(idx).setText(group.getName());
ShipFilterComposite.this.groupCompo.layout();
}
}
/* (非 Javadoc)
* @see logbook.gui.logic.ShipGroupListener#groupShipChanged(logbook.config.bean.ShipGroupBean)
*/
@Override
public void groupShipChanged(ShipGroupBean group) {
// TODO 自動生成されたメソッド・スタブ
}
};
ShipGroupObserver.addListener(shipGroupListner);
this.addListener(SWT.Dispose, new Listener() {
@Override
public void handleEvent(Event event) {
ShipGroupObserver.removeListener(shipGroupListner);
}
});
}
/**
* 現在のデータでパネル表示内容を更新
* @param filter
*/
public void updateContents(ShipFilterDto filter) {
this.updateContents(filter, this.panelVisible, this.etcVisible);
}
public void updateContents(ShipFilterDto filter, boolean panelVisible, boolean etcVisible) {
this.changeEnabled = false;
Set<String> items = new TreeSet<String>();
for (ItemDto entry : GlobalContext.getItemMap().values()) {
items.add(entry.getName());
}
this.nametext.remove(0, this.nametext.getItemCount() - 1);
for (String name : items) {
this.nametext.add(name);
}
this.recreateGroupButtons();
this.recreateShipTypeButtonos();
this.applyFilter(filter);
this.setPanelVisible(panelVisible, etcVisible);
this.changeEnabled = true;
}
private void switchMenuSelected(SelectionEvent e) {
MenuItem selectedItem = (MenuItem) e.widget;
int mode = !selectedItem.getSelection() ? 2 :
(selectedItem == this.groupMenuItem) ? 0 : 1;
this.setGroupMode(mode);
//this.shipTable.getFilterMenu().setGroupMode(this.groupMode);
if (this.changeEnabled) {
this.shipTable.updateFilter(this.createFilter(), true);
this.shipTable.getShell().layout();
}
}
private void switchPanel() {
LayoutLogic.hide(this.groupCompo, this.groupMode != 0);
LayoutLogic.hide(this.typeCompo, this.groupMode != 1);
LayoutLogic.hide(this.etcCompo, !this.etcVisible);
}
public int getGroupMode() {
return this.groupMode;
}
public void setGroupMode(int mode) {
if (this.groupMode != mode) {
this.groupMode = mode;
this.groupMenuItem.setSelection(mode == 0);
this.typeMenuItem.setSelection(mode == 1);
if (this.panelVisible) {
this.switchPanel();
//this.switchCompo.layout();
this.layout();
}
}
}
public boolean getPanelVisible() {
return this.panelVisible;
}
public boolean getEtcVisible() {
return this.etcVisible;
}
public void setPanelVisible(boolean panelVisible, boolean etcVisible) {
if ((this.etcVisible != etcVisible) || (this.panelVisible != panelVisible)) {
this.etcVisible = etcVisible;
this.panelVisible = panelVisible;
this.etcMenuItem.setSelection(etcVisible);
LayoutLogic.hide(this, !panelVisible);
if (panelVisible) {
this.switchPanel();
this.layout();
}
}
}
private static void setMenu(Control c, Menu ma) {
if (c instanceof Composite) {
for (final Control cc : ((Composite) c).getChildren()) {
setMenu(cc, ma);
}
}
c.setMenu(ma);
}
/**
* 艦種カテゴリボタンが押された
*/
private void categoryButtonSelected(Button source) {
this.typeCompo.setRedraw(false);
// まずはすべてオフ
for (Button check : this.typeButtons.values()) {
check.setSelection(false);
}
this.selectall.setSelection(false);
// 指定されたものだけオン
int[] types = (int[]) source.getData();
for (int type : types) {
Button button = this.typeButtons.get(type);
if (button != null) {
button.setSelection(true);
}
}
this.typeCompo.setRedraw(true);
if (this.changeEnabled)
this.shipTable.updateFilter(this.createFilter(), true);
}
/**
* グループボタンを削除して再作成
*/
private void recreateGroupButtons() {
for (Button button : this.groupButtons) {
button.setMenu(null);
button.dispose();
}
this.groupButtons.clear();
SelectionListener listener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Button button = (Button) e.getSource();
if (button.getSelection()) {
ShipFilterComposite.this.groupButtonSelected(button, button.getData());
}
}
};
for (ShipGroupBean group : ShipGroupConfig.get().getGroup()) {
Button button = new Button(this.groupCompo, SWT.RADIO);
button.setText(group.getName());
button.setData(group);
button.addSelectionListener(listener);
button.setMenu(this.switchMenu);
if (this.shipTable.getFilter().group == group) {
button.setSelection(true);
}
this.groupButtons.add(button);
}
this.groupCompo.layout();
}
/**
* 艦種ボタンを削除して再作成
*/
private void recreateShipTypeButtonos() {
for (Button button : this.typeButtons.values()) {
button.setMenu(null);
button.dispose();
}
this.typeButtons.clear();
SelectionListener listener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Button button = (Button) e.getSource();
if (button.getSelection() == false) {
// 艦種のどれかがOFFになったらオフにする
ShipFilterComposite.this.selectall.setSelection(false);
}
if (ShipFilterComposite.this.changeEnabled)
ShipFilterComposite.this.shipTable.updateFilter(ShipFilterComposite.this.createFilter(), true);
}
};
for (MasterData.ShipTypeDto type : MasterData.get().getStart2().getStype()) {
String name = type.getName();
int key = type.getId();
if (AppConstants.SHIP_TYPE_INFO.containsKey(key)) {
name = AppConstants.SHIP_TYPE_INFO.get(key);
if (name.equals("#")) {
// この艦種は表示しない
continue;
}
}
Button button = new Button(this.typeCheckCompo, SWT.CHECK);
button.setText(name);
button.setData(key);
button.setSelection(true);
button.addSelectionListener(listener);
button.setMenu(this.switchMenu);
this.typeButtons.put(key, button);
this.maxTypeId = Math.max(key, this.maxTypeId);
}
this.typeCheckCompo.layout();
}
/**
* フィルタデータをパネルに反映
* グループや艦種などが作られている必要がある
* @param filter
*/
public void applyFilter(ShipFilterDto filter) {
// 選択状態を初期化
this.groupAllButton.setSelection(false);
for (Button button : this.groupButtons) {
button.setSelection(false);
}
for (Button button : this.typeButtons.values()) {
button.setSelection(true);
}
this.lockedNo.setSelection(false);
this.lockedOnly.setSelection(false);
this.lockedAny.setSelection(false);
// 名前
if (!StringUtils.isEmpty(filter.nametext)) {
this.nametext.setText(filter.nametext);
}
// 名前.正規表現を使用する
this.regexp.setSelection(filter.regexp);
// 艦種設定
boolean allselected = true;
if (filter.enabledType != null) {
for (int i = 0; i < filter.enabledType.length; ++i) {
if (this.typeButtons.containsKey(i)) {
if (filter.enabledType[i] == false) {
allselected = false;
}
this.typeButtons.get(i).setSelection(filter.enabledType[i]);
}
}
}
this.selectall.setSelection(allselected);
// グループ
Button selectedGroupButton = this.groupAllButton;
if (filter.group != null) {
int idx = ShipGroupConfig.get().getGroup().indexOf(filter.group);
if (idx != -1) {
selectedGroupButton = this.groupButtons.get(idx);
}
}
this.selectedGroup = filter.group;
selectedGroupButton.setSelection(true);
// 鍵付き?
if (filter.locked == false) {
this.lockedNo.setSelection(true);
}
else if (filter.notlocked == false) {
this.lockedOnly.setSelection(true);
}
else {
this.lockedAny.setSelection(true);
}
// 艦隊に所属
if (filter.onfleet == false) {
this.fleetNo.setSelection(true);
}
else if (filter.notonfleet == false) {
this.fleetOnly.setSelection(true);
}
else {
this.fleetAny.setSelection(true);
}
// 遠征中を除外
this.ignoreOnMission.setSelection(!filter.mission);
// お風呂に入りたい
this.needBath.setSelection(!filter.notneedbath);
// タブ選択
this.setGroupMode(filter.groupMode);
}
public Combo getSearchCombo() {
return this.nametext;
}
private void groupButtonSelected(Button button, Object data) {
// ラジオボタンはOFFになった時もSelectedが呼ばれるのでONになったものだけ処理する
if (this.changeEnabled && button.getSelection()) {
this.selectedGroup = null;
if (button != this.groupAllButton) {
this.selectedGroup = (ShipGroupBean) data;
}
this.shipTable.updateFilter(this.createFilter(), true);
}
}
/**
* フィルターを構成する
*
* @return フィルター
*/
public ShipFilterDto createFilter() {
ShipFilterDto filter = this.shipTable.getFilter();
filter.nametext = this.nametext.getText();
filter.regexp = this.regexp.getSelection();
filter.enabledType = new boolean[this.maxTypeId + 1];
for (Button button : this.typeButtons.values()) {
Integer id = (Integer) button.getData();
filter.enabledType[id] = button.getSelection();
}
filter.group = this.selectedGroup;
if (this.lockedAny.getSelection()) {
filter.locked = filter.notlocked = true;
}
else if (this.lockedOnly.getSelection()) {
filter.locked = true;
filter.notlocked = false;
}
else {
filter.locked = false;
filter.notlocked = true;
}
if (this.fleetAny.getSelection()) {
filter.onfleet = filter.notonfleet = true;
}
else if (this.fleetOnly.getSelection()) {
filter.onfleet = true;
filter.notonfleet = false;
}
else {
filter.onfleet = false;
filter.notonfleet = true;
}
filter.mission = !this.ignoreOnMission.getSelection();
filter.notmission = true;
filter.needbath = true;
filter.notneedbath = !this.needBath.getSelection();
filter.groupMode = this.groupMode;
return filter;
}
}