Package de.lessvoid.nifty.controls.listbox

Source Code of de.lessvoid.nifty.controls.listbox.ListBoxControl

package de.lessvoid.nifty.controls.listbox;

import java.util.Comparator;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;

import org.bushe.swing.event.EventTopicSubscriber;

import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.NiftyIdCreator;
import de.lessvoid.nifty.controls.AbstractController;
import de.lessvoid.nifty.controls.ListBox;
import de.lessvoid.nifty.controls.ListBoxSelectionChangedEvent;
import de.lessvoid.nifty.controls.Scrollbar;
import de.lessvoid.nifty.controls.ScrollbarChangedEvent;
import de.lessvoid.nifty.controls.dynamic.CustomControlCreator;
import de.lessvoid.nifty.effects.EffectEventId;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.elements.events.ElementShowEvent;
import de.lessvoid.nifty.input.NiftyInputEvent;
import de.lessvoid.nifty.input.NiftyMouseInputEvent;
import de.lessvoid.nifty.loaderv2.types.ControlType;
import de.lessvoid.nifty.loaderv2.types.ElementType;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.tools.SizeValue;
import de.lessvoid.xml.xpp3.Attributes;

/**
* @deprecated Please use {@link de.lessvoid.nifty.controls.ListBox} when accessing NiftyControls.
*/
@Deprecated
public class ListBoxControl<T> extends AbstractController implements ListBox<T>, ListBoxView<T> {
  private Logger log = Logger.getLogger(ListBoxControl.class.getName());
  private ListBoxImpl<T> listBoxImpl = new ListBoxImpl<T>(this);
  private Element[] labelElements;
  private Nifty nifty;
  private Screen screen;
  private ScrollbarMode verticalScrollbar;
  private Element verticalScrollbarTemplate;
  private Element scrollElement;
  private ScrollbarMode horizontalScrollbar;
  private Element horizontalScrollbarTemplate;
  private Element childRootElement;
  private Element labelTemplateElement;
  private Element listBoxPanelElement;
  private Element bottomRightTemplate;
  private int labelTemplateHeight;
  private Properties parameter;
  private int displayItems;
  private ListBoxViewConverter<T> viewConverter;
  private EventTopicSubscriber<ScrollbarChangedEvent> verticalScrollbarSubscriber = new EventTopicSubscriber<ScrollbarChangedEvent>() {
    @Override
    public void onEvent(final String id, final ScrollbarChangedEvent event) {
      listBoxImpl.updateView((int) (event.getValue() / labelTemplateHeight));
    }
  };
  private EventTopicSubscriber<ScrollbarChangedEvent> horizontalScrollbarSubscriber = new EventTopicSubscriber<ScrollbarChangedEvent>() {
    @Override
    public void onEvent(final String id, final ScrollbarChangedEvent event) {
      if (childRootElement != null) {
        childRootElement.setConstraintX(new SizeValue(-(int) event.getValue() + "px"));
        childRootElement.getParent().layoutElements();
      }
    }
  };
  private EventTopicSubscriber<ElementShowEvent> listBoxControlShowEventSubscriber = new EventTopicSubscriber<ElementShowEvent>() {
    @Override
    public void onEvent(final String id, final ElementShowEvent event) {
      listBoxImpl.updateView();
    }
  };
  private int lastMaxWidth;
  private int applyWidthConstraintsLastWidth = -1;

  public void bind(
      final Nifty niftyParam,
      final Screen screenParam,
      final Element elementParam,
      final Properties parameterParam,
      final Attributes controlDefinitionAttributes) {
    super.bind(elementParam);

    nifty = niftyParam;
    screen = screenParam;
    parameter = parameterParam;
    viewConverter = createViewConverter(parameter.getProperty("viewConverterClass", ListBoxViewConverterSimple.class.getName()));
    verticalScrollbar = getScrollbarMode("vertical");
    verticalScrollbarTemplate = getElement().findElementByName("#vertical-scrollbar");
    horizontalScrollbar = getScrollbarMode("horizontal");
    horizontalScrollbarTemplate = getElement().findElementByName("#horizontal-scrollbar-parent");
    bottomRightTemplate = getElement().findElementByName("#bottom-right");
    displayItems = new Integer(parameter.getProperty("displayItems", "2"));
    scrollElement = getElement().findElementByName("#scrollpanel");
    applyWidthConstraintsLastWidth = -1;

    childRootElement = getElement().findElementByName("#child-root");
    if (!childRootElement.getElements().isEmpty()) {
      labelTemplateElement = childRootElement.getElements().get(0);
    }
    labelElements = new Element[displayItems];
    listBoxPanelElement = getElement().findElementByName("#panel");

    initSelectionMode(listBoxImpl, parameter.getProperty("selectionMode", "Single"), parameter.getProperty("forceSelection", "false"));
    connectListBoxAndListBoxPanel();
    listBoxImpl.bindToView(this, displayItems);
    lastMaxWidth = childRootElement.getWidth();
    ensureVerticalScrollbar();
    initLabelTemplateData();
    createLabels();
    initializeScrollPanel(screen);
    setElementHeight();
    initializeScrollElementHeight();
    listBoxImpl.updateView(0);
    initializeHorizontalScrollbar();
    initializeVerticalScrollbar(screen, labelTemplateHeight, 0);
  }

  @Override
  public void init(final Properties parameter, final Attributes controlDefinitionAttributes) {
    listBoxImpl.updateViewTotalCount();

    subscribeHorizontalScrollbar();
    subscribeVerticalScrollbar();
    nifty.subscribe(screen, getId(), ElementShowEvent.class, listBoxControlShowEventSubscriber);

    super.init(parameter, controlDefinitionAttributes);
  }

  @Override
  public void onStartScreen() {
  }

  public void mouseWheel(final Element e, final NiftyMouseInputEvent inputEvent) {
    int mouseWheel = inputEvent.getMouseWheel();
    Scrollbar scrollbar = getVerticalScrollbar();
    if (scrollbar != null) {
      float currentValue = scrollbar.getValue();
      if (mouseWheel < 0) {
        scrollbar.setValue(currentValue - scrollbar.getButtonStepSize() * mouseWheel);
      } else if (mouseWheel > 0) {
        scrollbar.setValue(currentValue - scrollbar.getButtonStepSize() * mouseWheel);
      }
    }
  }

  private void subscribeVerticalScrollbar() {
    Element scrollbar = getElement().findElementByName("#vertical-scrollbar");
    if (scrollbar != null) {
      nifty.subscribe(screen, scrollbar.getId(), ScrollbarChangedEvent.class, verticalScrollbarSubscriber);
    }
  }

  private void subscribeHorizontalScrollbar() {
    Element scrollbar = getElement().findElementByName("#horizontal-scrollbar");
    if (scrollbar != null) {
      nifty.subscribe(screen, scrollbar.getId(), ScrollbarChangedEvent.class, horizontalScrollbarSubscriber);
    }
  }

  private void unsubscribeVerticalScrollbar() {
    Element scrollbar = getElement().findElementByName("#vertical-scrollbar");
    if (scrollbar != null) {
      nifty.unsubscribe(scrollbar.getId(), verticalScrollbarSubscriber);
    }
  }

  private void unsubscribeHorizontalScrollbar() {
    Element scrollbar = getElement().findElementByName("#horizontal-scrollbar");
    if (scrollbar != null) {
      nifty.unsubscribe(scrollbar.getId(), horizontalScrollbarSubscriber);
    }
  }

  @Override
  public boolean inputEvent(final NiftyInputEvent inputEvent) {
    return false;
  }

  @Override
  public void onFocus(final boolean getFocus) {
    super.onFocus(getFocus);
  }

  public void setFocus() {
    childRootElement.setFocus();
  }

  @SuppressWarnings({ "unchecked", "rawtypes" })
  private ListBoxViewConverter<T> createViewConverter(final String className) {
    try {
      return (ListBoxViewConverter<T>) Class.forName(className).newInstance();
    } catch (Exception e) {
      log.warning("Unable to instantiate given class [" + className + "] with error: " + e.getMessage());
      e.printStackTrace();
      return new ListBoxViewConverterSimple();
    }
  }

  public ListBoxViewConverter<T> getViewConverter() {
    return viewConverter;
  }

  // ListBoxView Interface implementation

  @Override
  public void display(final List<T> visibleItems, final int focusElement, final List<Integer> selectedElements) {
    ensureWidthConstraints();
    for (int i = 0; i < visibleItems.size(); i++) {
      T item = visibleItems.get(i);
      if (labelElements[i] != null) {
        labelElements[i].setVisible(item != null && getElement().isVisible());
        if (item != null) {
          displayElement(i, item);
          setListBoxItemIndex(i);
          handleElementFocus(i, focusElement);
          handleElementSelection(i, item, selectedElements);
        }
      }
    }
  }

  @Override
  public void updateTotalCount(final int newCount) {
    if (verticalScrollbar == ScrollbarMode.optional) {
      Element vertical = getElement().findElementByName("#vertical-scrollbar");
      if (newCount > displayItems) {
        if (vertical == null) {
          ElementType templateType = verticalScrollbarTemplate.getElementType().copy();
          CustomControlCreator create = new CustomControlCreator((ControlType) templateType);
          Element e = create.create(nifty, screen, scrollElement);
          if (e.getHeight() < 23*2) { // ugly
            nifty.removeElement(screen, e);
            return;
          }
          subscribeVerticalScrollbar();
          ensureWidthConstraints();

          updateBottomRightElement();
          nifty.executeEndOfFrameElementActions();
          screen.layoutLayers();
        }
      } else if (newCount <= displayItems) {
        if (vertical != null) {
          unsubscribeVerticalScrollbar();
          nifty.removeElement(screen, vertical);
          nifty.executeEndOfFrameElementActions();
          ensureWidthConstraints();

          updateBottomRightElement();
          nifty.executeEndOfFrameElementActions();
          screen.layoutLayers();
        }
      }
    }
    initializeVerticalScrollbar(screen, labelTemplateHeight, newCount);
  }

  @Override
  public void updateTotalWidth(final int newWidth) {
    this.lastMaxWidth = newWidth;
    if (horizontalScrollbar == ScrollbarMode.optional) {
      Element horizontal = getElement().findElementByName("#horizontal-scrollbar-parent");
      if (newWidth > listBoxPanelElement.getWidth()) {
        if (horizontal == null) {
          nifty.createElementFromType(screen, getElement(), horizontalScrollbarTemplate.getElementType());

          updateBottomRightElement();
          nifty.executeEndOfFrameElementActions();
          screen.layoutLayers();

          setElementHeight();
          subscribeHorizontalScrollbar();
        }
      } else if (newWidth <= listBoxPanelElement.getWidth()) {
        if (horizontal != null) {
          unsubscribeHorizontalScrollbar();
          nifty.removeElement(screen, horizontal);
          nifty.executeEndOfFrameElementActions();
          setElementHeight();
        }
      }
    }   
    initializeHorizontalScrollbar();
    ensureWidthConstraints();
  }

  public void ensureWidthConstraints() {
    applyWidthConstraints(Math.max(lastMaxWidth, listBoxPanelElement.getWidth()));
  }

  @Override
  public void layoutCallback() {
    if (listBoxPanelElement == null) {
      return;
    }
    ensureWidthConstraints();
    initializeHorizontalScrollbar();
  }

  private void applyWidthConstraints(final int width) {
    if (applyWidthConstraintsLastWidth  == width) {
      return;
    }

    applyWidthConstraintsLastWidth = width;
    SizeValue newWidthSizeValue = new SizeValue(width + "px");
    for (Element element : labelElements) {
      if (element != null) {
        element.setConstraintWidth(newWidthSizeValue);
      }
    }
    childRootElement.setConstraintWidth(newWidthSizeValue);
    getElement().layoutElements();
  }

  @Override
  public void scrollTo(final int newPosition) {
    Scrollbar verticalS = getVerticalScrollbar();
    if (verticalS != null) {
      verticalS.setValue(newPosition * labelTemplateHeight);
    }
  }

  @Override
  public int getWidth(final T item) {
    return viewConverter.getWidth(labelElements[0], item);
  }

  // ListBox Interface Implementation

  @Override
  public void changeSelectionMode(final SelectionMode listBoxSelectionMode, final boolean forceSelection) {
    listBoxImpl.changeSelectionMode(listBoxSelectionMode, forceSelection);
  }

  @Override
  public void addItem(final T newItem) {
    listBoxImpl.addItem(newItem);
  }

  @Override
  public void insertItem(final T item, final int index) {
    listBoxImpl.insertItem(item, index);
  }

  @Override
  public int itemCount() {
    return listBoxImpl.itemCount();
  }

  @Override
  public void clear() {
    listBoxImpl.clear();
  }

  @Override
  public void selectItemByIndex(final int selectionIndex) {
    listBoxImpl.selectItemByIndex(selectionIndex);
  }

  @Override
  public void selectItem(final T item) {
    listBoxImpl.selectItem(item);
  }

  @Override
  public void selectNext() {
    listBoxImpl.selectNext();
  }

  @Override
  public void selectPrevious() {
    listBoxImpl.selectPrevious();
  }

  @Override
  public void deselectItemByIndex(final int itemIndex) {
    listBoxImpl.deselectItemByIndex(itemIndex);
  }

  @Override
  public void deselectItem(final T item) {
    listBoxImpl.deselectItem(item);
  }

  @Override
  public List<T> getSelection() {
    return listBoxImpl.getSelection();
  }

  @Override
  public List<Integer> getSelectedIndices() {
    return listBoxImpl.getSelectedIndices();
  }

  @Override
  public void removeItemByIndex(final int itemIndex) {
    listBoxImpl.removeItemByIndex(itemIndex);
  }

  @Override
  public void removeItem(final T item) {
    listBoxImpl.removeItem(item);
  }

  @Override
  public List<T> getItems() {
    return listBoxImpl.getItems();
  }

  @Override
  public void showItem(final T item) {
    listBoxImpl.showItem(item);
  }

  @Override
  public void showItemByIndex(final int itemIndex) {
    listBoxImpl.showItemByIndex(itemIndex);
  }

  @Override
  public void setFocusItem(final T item) {
    listBoxImpl.setFocusItem(item);
  }

  @Override
  public void setFocusItemByIndex(final int itemIndex) {
    listBoxImpl.setFocusItemByIndex(itemIndex);
  }

  @Override
  public T getFocusItem() {
    return listBoxImpl.getFocusItem();
  }

  @Override
  public int getFocusItemIndex() {
    return listBoxImpl.getFocusItemIndex();
  }

  @Override
  public void setListBoxViewConverter(final ListBoxViewConverter<T> viewConverter) {
    this.viewConverter = viewConverter;
  }

  @Override
  public void publish(final ListBoxSelectionChangedEvent<T> event) {
    if (getElement().getId() != null) {
      nifty.publishEvent(getElement().getId(), event);
    }
  }

  @Override
  public void addAllItems(final List<T> itemsToAdd) {
    listBoxImpl.addAllItems(itemsToAdd);
  }

  @Override
  public void removeAllItems(final List<T> itemsToRemove) {
    listBoxImpl.removeAllItems(itemsToRemove);
  }

  @Override
  public void sortAllItems() {
    listBoxImpl.sortItems(null);
  }

  @Override
  public void sortAllItems(final Comparator<T> comperator) {
    listBoxImpl.sortItems(comperator);
  }

  @Override
  public int getDisplayItemCount() {
    return displayItems;
  }

  @Override
  public void refresh() {
    listBoxImpl.updateView();
  }

  // internals

  private void initSelectionMode(final ListBoxImpl<T> listBoxImpl, final String selectionMode, final String forceSelection) {
    SelectionMode listBoxSelectionMode = SelectionMode.Single;
    try {
      listBoxSelectionMode = SelectionMode.valueOf(selectionMode);
    } catch (RuntimeException e) {
      log.warning("Unsupported value for selectionMode [" + selectionMode + "]. Fall back to using single selection mode.");
    }

    listBoxImpl.changeSelectionMode(listBoxSelectionMode, "true".equalsIgnoreCase(forceSelection));
  }

  private void initializeScrollPanel(final Screen screen) {
    if (horizontalScrollbar == ScrollbarMode.off || horizontalScrollbar == ScrollbarMode.optional) {
      Element horizontal = getElement().findElementByName("#horizontal-scrollbar-parent");
      if (horizontal != null) {
        nifty.removeElement(screen, horizontal);
      }
    }
    if (verticalScrollbar == ScrollbarMode.off || verticalScrollbar == ScrollbarMode.optional) {
      Element vertical = getElement().findElementByName("#vertical-scrollbar");
      if (vertical != null) {
        nifty.removeElement(screen, vertical);
      }
    }

    childRootElement.setConstraintX(new SizeValue("0px"));
    childRootElement.setConstraintY(new SizeValue("0px"));

    updateBottomRightElement();
    nifty.executeEndOfFrameElementActions();
    screen.layoutLayers();
  }

  private void updateBottomRightElement() {
    Element horizontal = getElement().findElementByName("#horizontal-scrollbar-parent");
    Element vertical = getElement().findElementByName("#vertical-scrollbar");
    Element bottomRight = getElement().findElementByName("#bottom-right");
    if (horizontal != null) {
      if (vertical == null) {
        if (bottomRight != null) {
          nifty.removeElement(screen, bottomRight);
          nifty.executeEndOfFrameElementActions();
          initializeHorizontalScrollbar();
        }
      } else {
        if (bottomRight == null) {
          nifty.createElementFromType(screen, horizontal, bottomRightTemplate.getElementType());
          initializeHorizontalScrollbar();
        }
      }
    }
  }

  private void initializeHorizontalScrollbar() {
    Scrollbar horizontalS = getHorizontalScrollbar();
    if (horizontalS != null && horizontalS.isBound()) {
      horizontalS.setWorldMax(lastMaxWidth);
      horizontalS.setWorldPageSize(listBoxPanelElement.getWidth());
    }
  }

  private void initializeVerticalScrollbar(final Screen screen, final float labelTemplateHeight, final int itemCount) {
    Scrollbar verticalS = getVerticalScrollbar();
    if (verticalS != null && verticalS.isBound()) {
      verticalS.setWorldMax(itemCount * labelTemplateHeight);
      verticalS.setWorldPageSize(displayItems * labelTemplateHeight);
      verticalS.setButtonStepSize(labelTemplateHeight);
    }
  }

  @SuppressWarnings("unchecked")
  private void createLabels() {
    if (labelTemplateElement == null) {
      return;
    }
    for (Element e : childRootElement.getElements()) {
      nifty.removeElement(screen, e);
    }   
    for (int i = 0; i < displayItems; i++) {
      ElementType templateType = labelTemplateElement.getElementType().copy();
      templateType.getAttributes().set("id", NiftyIdCreator.generate());
      labelElements[i] = nifty.createElementFromType(screen, childRootElement, templateType);

      // connect it to this listbox
      ListBoxItemController<T> listBoxItemController = labelElements[i].getControl(ListBoxItemController.class);
      if (listBoxItemController != null) {
        listBoxItemController.setListBox(listBoxImpl);
      }
    }
  }

  private void initializeScrollElementHeight() {
    scrollElement.setConstraintHeight(new SizeValue(displayItems * labelTemplateHeight + "px"));
  }

  private void ensureVerticalScrollbar() {
    if (displayItems == 1) {
      verticalScrollbar = ScrollbarMode.off;
    }
  }

  private void setElementHeight() {
    getElement().setConstraintHeight(new SizeValue(displayItems * labelTemplateHeight + findHorizontalScrollbarHeight() + "px"));
    screen.layoutLayers();
  }

  private int findHorizontalScrollbarHeight() {
    int horizontalScrollbarElementHeight = 0;
    Element horizontalScrollbarElement = getElement().findElementByName("#horizontal-scrollbar");
    if (horizontalScrollbarElement != null) {
      horizontalScrollbarElementHeight = horizontalScrollbarElement.getHeight();
    }
    return horizontalScrollbarElementHeight;
  }

  private void initLabelTemplateData() {
    if (labelTemplateElement == null) {
      return;
    }
    labelTemplateElement.getParent().layoutElements();
    labelTemplateHeight = labelTemplateElement.getHeight();
    nifty.removeElement(screen, labelTemplateElement);
  }

  @SuppressWarnings("unchecked")
  private void connectListBoxAndListBoxPanel() {
    ListBoxPanel<T> listBoxPanel = listBoxPanelElement.getControl(ListBoxPanel.class);
    listBoxPanel.setListBox(listBoxImpl);
  }

  private void displayElement(final int index, final T item) {
    viewConverter.display(labelElements[index], item);
  }

  private void handleElementSelection(final int index, final T item, final List<Integer> selectedElements) {
    if (item != null && selectedElements.contains(index)) {
      labelElements[index].startEffect(EffectEventId.onCustom, null, "select");
    } else {
      labelElements[index].resetSingleEffect(EffectEventId.onCustom, "select");
    }
  }

  @SuppressWarnings("unchecked")
  private void handleElementFocus(final int index, final int focusElement) {
    ListBoxPanel<T> listBoxPanel = listBoxPanelElement.getControl(ListBoxPanel.class);
    if (listBoxPanel.hasFocus()) {
      if (focusElement == index) {
        labelElements[index].startEffect(EffectEventId.onCustom, null, "focus");
      } else {
        labelElements[index].resetSingleEffect(EffectEventId.onCustom, "focus");
      }
    } else {
      labelElements[index].resetSingleEffect(EffectEventId.onCustom, "focus");
    }
  }

  @SuppressWarnings("unchecked")
  private void setListBoxItemIndex(final int itemIndex) {
    ListBoxItemController<T> listBoxItemController = labelElements[itemIndex].getControl(ListBoxItemController.class);
    if (listBoxItemController != null) {
      listBoxItemController.setItemIndex(itemIndex);
    }
  }

  private Scrollbar getVerticalScrollbar() {
    return getScrollbar("#vertical-scrollbar");
  }

  private Scrollbar getHorizontalScrollbar() {
    return getScrollbar("#horizontal-scrollbar");
  }

  private Scrollbar getScrollbar(final String id) {
    return getElement().findNiftyControl(id, Scrollbar.class);
  }

  private ScrollbarMode getScrollbarMode(final String key) {
    try {
      return ScrollbarMode.valueOf(parameter.getProperty(key, ScrollbarMode.on.toString()));
    } catch (Exception e) {
      log.warning("unknown scrollbar mode [" + key + "] falling back to 'on'");
      return ScrollbarMode.on;
    }
  }

  private enum ScrollbarMode {
    off,
    on,
    optional
  }
}
TOP

Related Classes of de.lessvoid.nifty.controls.listbox.ListBoxControl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.