/* * ****************************************************************************** * * Copyright 2015 See AUTHORS file. * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * ***************************************************************************** */ package com.uwsoft.editor.view.ui.box; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.ui.Cell; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.utils.Array; import com.kotcrab.vis.ui.VisUI; import com.kotcrab.vis.ui.widget.VisImageButton; import com.kotcrab.vis.ui.widget.VisScrollPane; import com.kotcrab.vis.ui.widget.VisTable; import com.kotcrab.vis.ui.widget.VisTextField; import com.uwsoft.editor.Overlap2DFacade; import com.uwsoft.editor.event.KeyboardListener; import com.uwsoft.editor.renderer.data.LayerItemVO; import com.uwsoft.editor.utils.InputFilters; import com.uwsoft.editor.utils.StandardWidgetsFactory; /** * Created by azakhary on 4/17/2015. */ public class UILayerBox extends UICollapsibleBox { private static final String prefix = "com.uwsoft.editor.view.ui.box.UILayerBox"; public static final String LAYER_ROW_CLICKED = prefix + ".LAYER_ROW_CLICKED"; public static final String CREATE_NEW_LAYER = prefix + ".CREATE_NEW_LAYER"; public static final String DELETE_LAYER = prefix + ".DELETE_NEW_LAYER"; public static final String CHANGE_LAYER_NAME = prefix + ".CHANGE_LAYER_NAME"; public static final String LOCK_LAYER = prefix + ".LOCK_LAYER"; public static final String UNLOCK_LAYER = prefix + ".UNLOCK_LAYER"; public static final String HIDE_LAYER = prefix + ".HIDE_LAYER"; public static final String UNHIDE_LAYER = prefix + ".UNHIDE_LAYER"; public static final String LAYER_DROPPED = prefix + ".LAYER_DROPPED"; private final DragAndDrop dragAndDrop; public int currentSelectedLayerIndex = 0; private Overlap2DFacade facade; private VisTable contentTable; private VisTable bottomPane; private VisScrollPane scrollPane; private VisTable layersTable; private SlotSource sourceInEdition; private Array<UILayerItemSlot> rows = new Array<>(); public UILayerBox() { super("Layers", 222); facade = Overlap2DFacade.getInstance(); setMovable(false); contentTable = new VisTable(); layersTable = new VisTable(); scrollPane = new VisScrollPane(layersTable); scrollPane.setFadeScrollBars(false); contentTable.add(scrollPane).padTop(2).width(221).height(150); layersTable.top(); scrollPane.layout(); bottomPane = new VisTable(); contentTable.row(); contentTable.add(bottomPane).expandX().fillX(); VisImageButton newBtn = new VisImageButton("new-layer-button"); VisImageButton deleteBtn = new VisImageButton("trash-button"); bottomPane.add().expandX(); bottomPane.add(newBtn).right().pad(3); bottomPane.add(deleteBtn).right().pad(3); newBtn.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { facade.sendNotification(CREATE_NEW_LAYER); } }); deleteBtn.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { facade.sendNotification(DELETE_LAYER); } }); dragAndDrop = new DragAndDrop(); createCollapsibleWidget(contentTable); } public void enableDraggingInEditedSlot() { if(sourceInEdition != null) { dragAndDrop.addSource(sourceInEdition); sourceInEdition = null; } } public void disableDraggingInEditedSlot() { if(sourceInEdition != null) { dragAndDrop.removeSource(sourceInEdition); } } public int getCurrentSelectedLayerIndex() { return currentSelectedLayerIndex; } public int getRowCount() { return rows.size; } public UILayerItem getCurrentSelectedLayer() { return rows.get(rows.size-1-currentSelectedLayerIndex).uiLayerItem; } public void clearItems() { layersTable.clear(); rows.clear(); } public void clearSelection() { for (int i = 0; i < rows.size; i++) { rows.get(i).getUiLayerItem().setSelected(false); } currentSelectedLayerIndex = -1; } public void setCurrentSelectedLayer(int index) { if(index == -1) return; UILayerItemSlot slot = rows.get(rows.size-1-index); clearSelection(); slot.getUiLayerItem().setSelected(true); } public void addItem(LayerItemVO itemVO) { UILayerItemSlot itemSlot = new UILayerItemSlot(); UILayerItem item = new UILayerItem(itemVO, itemSlot); layersTable.add(itemSlot).left().expandX().fillX(); layersTable.row().padTop(1); SlotSource sourceItem = new SlotSource(item); dragAndDrop.addSource(sourceItem); dragAndDrop.addTarget(new SlotTarget(itemSlot)); dragAndDrop.setDragActorPosition(0, 0); rows.add(itemSlot); itemSlot.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { super.clicked(event, x, y); VisTextField textField = itemSlot.getUiLayerItem().getNameField(); if(sourceInEdition != null) { VisTextField prevField = ((UILayerItem) sourceInEdition.getActor()).getNameField(); if(textField != prevField) { prevField.clearSelection(); prevField.setDisabled(true); enableDraggingInEditedSlot(); } } clearSelection(); itemSlot.getUiLayerItem().setSelected(true); currentSelectedLayerIndex = rows.size - rows.indexOf(itemSlot, true) - 1; facade.sendNotification(LAYER_ROW_CLICKED, itemSlot.getUiLayerItem()); // Change name mode if double click if(getTapCount() == 2 && !itemSlot.getUiLayerItem().getData().isLocked) { sourceInEdition = sourceItem; textField.setDisabled(false); textField.focusField(); textField.selectAll(); disableDraggingInEditedSlot(); } } }); } private static class SlotSource extends DragAndDrop.Source { public SlotSource(UILayerItem item) { super(item); } @Override public DragAndDrop.Payload dragStart(InputEvent event, float x, float y, int pointer) { DragAndDrop.Payload payload = new DragAndDrop.Payload(); payload.setDragActor(new UILayerItemDragActor((UILayerItem) getActor())); return payload; } @Override public void dragStop(InputEvent event, float x, float y, int pointer, DragAndDrop.Payload payload, DragAndDrop.Target target) { UILayerItem uiLayerItemActor = (UILayerItem) getActor(); UILayerItemSlot uiLayerItemSlot = uiLayerItemActor.getItemSlot(); if (target != null) { UILayerItemSlot uiLayerItemSlotTarget = (UILayerItemSlot) target.getActor(); UILayerItem uiLayerItemTarget = uiLayerItemSlotTarget.getUiLayerItem(); // uiLayerItemActor.setItemSlot(uiLayerItemSlotTarget); uiLayerItemTarget.setItemSlot(uiLayerItemSlot); String sourceLayer = uiLayerItemActor.getLayerName(); String targetLayer = uiLayerItemTarget.getLayerName(); String[] notificationPayload = {sourceLayer, targetLayer}; Overlap2DFacade.getInstance().sendNotification(LAYER_DROPPED, notificationPayload); } else { uiLayerItemActor.setItemSlot(uiLayerItemSlot); } } } private static class SlotTarget extends DragAndDrop.Target { //private Slot targetSlot; public SlotTarget(UILayerItemSlot item) { super(item); } @Override public boolean drag(DragAndDrop.Source source, DragAndDrop.Payload payload, float x, float y, int pointer) { // Slot payloadSlot = (Slot) payload.getObject(); // // if (targetSlot.getItem() == payloadSlot.getItem() || // // targetSlot.getItem() == null) { // getActor().setColor(Color.BLUE); return true; // } else { // getActor().setColor(Color.DARK_GRAY); // return false; // } } @Override public void drop(DragAndDrop.Source source, DragAndDrop.Payload payload, float x, float y, int pointer) { //Overlap2DFacade.getInstance().sendNotification(LAYER_DROPPED); } @Override public void reset(DragAndDrop.Source source, DragAndDrop.Payload payload) { // getActor().setColor(Color.LIGHT_GRAY); } } public static class UILayerItemDragActor extends VisTable { public String layerName; public UILayerItemDragActor(UILayerItem actor) { layerName = actor.getLayerName(); setWidth(actor.getWidth()); setHeight(actor.getPrefHeight()); VisImageButton lockBtn = new VisImageButton("layer-lock"); VisImageButton visibleBtn = new VisImageButton("layer-visible"); add(lockBtn).left(); add(visibleBtn).left().padRight(6); add(actor.getLayerName()).expandX().fillX(); setBackground(VisUI.getSkin().getDrawable(actor.isSelected() ? "layer-bg-over" : "layer-bg")); getColor().a = .9f; } } public class UILayerItemSlot extends VisTable { private final Cell cell; private final Drawable normalBg; private final Drawable selectedBg; private UILayerItem uiLayerItem; public UILayerItemSlot() { normalBg = VisUI.getSkin().getDrawable("layer-bg"); selectedBg = VisUI.getSkin().getDrawable("layer-bg-over"); setBackground(normalBg); cell = add().expandX().fillX(); } private UILayerItemSlot(UILayerItemSlot uiLayerItemSlot) { this(); cell.width(uiLayerItemSlot.cell.getPrefWidth()); cell.height(uiLayerItemSlot.cell.getPrefHeight()); } public void setLayerItem(UILayerItem uiLayerItem) { this.uiLayerItem = uiLayerItem; cell.setActor(uiLayerItem); cell.height(uiLayerItem.getHeight()); } public UILayerItem getUiLayerItem() { return uiLayerItem; } public void setSelected(boolean selected) { setBackground(selected ? selectedBg : normalBg); } @Override protected UILayerItemSlot clone() throws CloneNotSupportedException { return new UILayerItemSlot(this); } } public class UILayerItem extends VisTable { private final LayerItemVO layerData; private UILayerItemSlot itemSlot; private boolean selected; private VisTextField layerNameField; public UILayerItem(LayerItemVO layerData, UILayerItemSlot itemSlot) { super(); this.layerData = layerData; this.itemSlot = itemSlot; VisImageButton lockBtn = new VisImageButton("layer-lock"); lockBtn.addListener(new CheckClickListener(lockBtn, LOCK_LAYER, UNLOCK_LAYER)); VisImageButton visibleBtn = new VisImageButton("layer-visible"); visibleBtn.addListener(new CheckClickListener(visibleBtn, HIDE_LAYER, UNHIDE_LAYER)); add(lockBtn).left(); add(visibleBtn).left().padRight(6); layerNameField = StandardWidgetsFactory.createTextField("transparent", false); layerNameField.setTextFieldFilter(InputFilters.ALPHANUMERIC); layerNameField.setText(layerData.layerName); layerNameField.setDisabled(true); // This listener will manage Enter and lost focus events layerNameField.addListener(new KeyboardListener(CHANGE_LAYER_NAME)); add(layerNameField).expandX().fillX(); lockBtn.setChecked(layerData.isLocked); visibleBtn.setChecked(!layerData.isVisible); itemSlot.setLayerItem(this); } public VisTextField getNameField() { return layerNameField; } public boolean isLocked() { return layerData.isLocked; } public boolean isSelected() { return selected; } public void setSelected(boolean selected) { this.selected = selected; itemSlot.setSelected(selected); } public LayerItemVO getData() { return layerData; } public boolean isLayerVisible() { return layerData.isVisible; } public String getLayerName() { return layerData.layerName; } public UILayerItemSlot getItemSlot() { return itemSlot; } public void setItemSlot(UILayerItemSlot itemSlot) { this.itemSlot = itemSlot; itemSlot.setLayerItem(this); itemSlot.setSelected(selected); } private class CheckClickListener extends ClickListener { final VisImageButton owner; final String eventOnUnchecking; final String eventOnChecking; CheckClickListener(VisImageButton owner, String eventOnUnchecking, String eventOnChecking) { this.owner = owner; this.eventOnChecking = eventOnChecking; this.eventOnUnchecking = eventOnUnchecking; } @Override public void clicked(InputEvent event, float x, float y) { super.clicked(event, x, y); final String sendEvent = (owner.isChecked())? eventOnUnchecking : eventOnChecking; facade.sendNotification(sendEvent, itemSlot.getUiLayerItem()); } } } public Array<UILayerItemSlot> getLayerSlots() { return rows; } }