Package org.jmol.shape

Source Code of org.jmol.shape.Labels

/* $RCSfile$
* $Author: hansonr $
* $Date: 2011-02-10 19:00:32 +0100 (jeu., 10 févr. 2011) $
* $Revision: 15145 $
*
* Copyright (C) 2002-2005  The Jmol Development Team
*
* Contact: jmol-developers@lists.sf.net
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License as published by the Free Software Foundation; either
*  version 2.1 of the License, or (at your option) any later version.
*
*  This library 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
*  Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/

package org.jmol.shape;

import org.jmol.g3d.*;
import org.jmol.modelset.Atom;
import org.jmol.modelset.LabelToken;
import org.jmol.util.ArrayUtil;
import org.jmol.util.BitSetUtil;
import org.jmol.util.Escape;
import org.jmol.viewer.ActionManager;
import org.jmol.viewer.JmolConstants;

import java.util.Hashtable;
import java.util.BitSet;

public class Labels extends AtomShape {

  String[] strings;
  String[] formats;
  short[] bgcolixes;
  byte[] fids;
  int[] offsets;

  private Hashtable atomLabels = new Hashtable();
  private Text text;

  private BitSet bsFontSet, bsBgColixSet;

  private int defaultOffset;
  private int defaultAlignment;
  private int defaultZPos;
  private byte defaultFontId;
  private short defaultColix;
  private short defaultBgcolix;
  private byte defaultPaletteID;
  private int defaultPointer;
  private static int zeroOffset = (JmolConstants.LABEL_DEFAULT_X_OFFSET << 8)
      | JmolConstants.LABEL_DEFAULT_Y_OFFSET;

  byte zeroFontId;

  private boolean defaultsOnlyForNone = true;
  private boolean setDefaults = false;
 
  //labels

  public void initShape() {
    super.initShape();
    defaultFontId = zeroFontId = g3d.getFont3D(JmolConstants.DEFAULT_FONTFACE,
        JmolConstants.DEFAULT_FONTSTYLE, JmolConstants.LABEL_DEFAULT_FONTSIZE).fid;
    defaultColix = 0; //"none" -- inherit from atom
    defaultBgcolix = 0; //"none" -- off
    defaultOffset = zeroOffset;
    defaultZPos = 0;
    translucentAllowed = false;
  }

  public void setProperty(String propertyName, Object value, BitSet bsSelected) {
    isActive = true;

    if ("setDefaults" == propertyName) {
      setDefaults = ((Boolean) value).booleanValue();
      return;
    }

    if ("color" == propertyName) {
      isActive = true;
      byte pid = JmolConstants.pidOf(value);
      short colix = Graphics3D.getColix(value);
      if (!setDefaults)
        for (int i = atomCount; --i >= 0;)
          if (bsSelected.get(i))
            setColix(i, colix, pid);
      if (setDefaults || !defaultsOnlyForNone) {
        defaultColix = colix;
        defaultPaletteID = pid;
      }
      return;
    }

    if ("scalereference" == propertyName) {
      if (strings == null)
        return;
      float val = ((Float) value).floatValue();
      float scalePixelsPerMicron = (val == 0 ? 0 : 10000f / val);
      for (int i = atomCount; --i >= 0;)
        if (bsSelected.get(i)) {
          if (strings.length <= i)
            continue;
          text = getLabel(i);
          if (text == null) {
            text = new Text(g3d, null, strings[i], (short) 0, (short) 0, 0, 0,
                0, 0, 0, scalePixelsPerMicron);
            putLabel(i, text);
          } else {
            text.setScalePixelsPerMicron(scalePixelsPerMicron);
          }
        }
      return;
    }

    if ("label" == propertyName) {
      setLabel((String) value, bsSelected);
      return;
    }

    if ("translucency" == propertyName || "bgtranslucency" == propertyName) {
      // no translucency
      return;
    }

    if ("bgcolor" == propertyName) {
      isActive = true;
      if (bsBgColixSet == null)
        bsBgColixSet = new BitSet();
      short bgcolix = Graphics3D.getColix(value);
      if (!setDefaults)
        for (int i = atomCount; --i >= 0;)
          if (bsSelected.get(i))
            setBgcolix(i, bgcolix);
      if (setDefaults || !defaultsOnlyForNone)
        defaultBgcolix = bgcolix;
      return;
    }

    // the rest require bsFontSet setting

    if (bsFontSet == null)
      bsFontSet = new BitSet();

    if ("fontsize" == propertyName) {
      int fontsize = ((Integer) value).intValue();
      if (fontsize < 0) {
        fids = null;
        return;
      }
      byte fid = g3d.getFontFid(fontsize);
      if (!setDefaults)
        for (int i = atomCount; --i >= 0;)
          if (bsSelected.get(i))
            setFont(i, fid);
      if (setDefaults || !defaultsOnlyForNone)
        defaultFontId = fid;
      return;
    }

    if ("font" == propertyName) {
      byte fid = ((Font3D) value).fid;
      if (!setDefaults)
        for (int i = atomCount; --i >= 0;)
          if (bsSelected.get(i))
            setFont(i, fid);
      if (setDefaults || !defaultsOnlyForNone)
        defaultFontId = fid;
      return;
    }

    if ("offset" == propertyName || "offsetexact" == propertyName) {
      int offset = ((Integer) value).intValue();
      // 0 must be the default, because we initialize the array
      // in segments and so there will be extra 0s.
      // but this "0" only means that "zero" offset; you
      // can change the default to anything you want.
      boolean isExact = (propertyName == "offsetexact");
      if (offset == 0)
        offset = Short.MAX_VALUE;
      else if (offset == zeroOffset)
        offset = 0;
      if (!setDefaults)
        for (int i = atomCount; --i >= 0;)
          if (bsSelected.get(i))
            setOffsets(i, offset, isExact);
      if (setDefaults || !defaultsOnlyForNone)
        defaultOffset = offset;
      return;
    }

    if ("align" == propertyName) {
      String type = (String) value;
      int alignment = Object2d.ALIGN_LEFT;
      if (type.equalsIgnoreCase("right"))
        alignment = Object2d.ALIGN_RIGHT;
      else if (type.equalsIgnoreCase("center"))
        alignment = Object2d.ALIGN_CENTER;
      for (int i = atomCount; --i >= 0;)
        if (bsSelected.get(i))
          setAlignment(i, alignment);
      if (setDefaults || !defaultsOnlyForNone)
        defaultAlignment = alignment;
      return;
    }

    if ("pointer" == propertyName) {
      int pointer = ((Integer) value).intValue();
      if (!setDefaults)
        for (int i = atomCount; --i >= 0;)
          if (bsSelected.get(i))
            setPointer(i, pointer);
      if (setDefaults || !defaultsOnlyForNone)
        defaultPointer = pointer;
      return;
    }

    if ("front" == propertyName) {
      boolean TF = ((Boolean) value).booleanValue();
      if (!setDefaults)
        for (int i = atomCount; --i >= 0;)
          if (bsSelected.get(i))
            setFront(i, TF);
      if (setDefaults || !defaultsOnlyForNone)
        defaultZPos = (TF ? FRONT_FLAG : 0);
      return;
    }

    if ("group" == propertyName) {
      boolean TF = ((Boolean) value).booleanValue();
      if (!setDefaults)
        for (int i = atomCount; --i >= 0;)
          if (bsSelected.get(i))
            setGroup(i, TF);
      if (setDefaults || !defaultsOnlyForNone)
        defaultZPos = (TF ? GROUP_FLAG : 0);
      return;
    }

    if ("display" == propertyName || "toggleLabel" == propertyName) {
      // toggle
      int mode = ("toggleLabel" == propertyName ? 0
          : ((Boolean) value).booleanValue() ? 1 : -1);
      if (mads == null)
        mads = new short[atomCount];
      for (int atomIndex = atomCount; --atomIndex >= 0;) {
        if (bsSelected.get(atomIndex)) {
          Atom atom = atoms[atomIndex];
          if (formats == null || atomIndex >= formats.length)
            formats = ArrayUtil.ensureLength(formats, atomIndex + 1);
          if (strings != null && strings.length > atomIndex
              && strings[atomIndex] != null) {
            mads[atomIndex] = (short) (mode == 0 && mads[atomIndex] <
                || mode == 1 ? 1 : -1);
          } else {
            if (bsSizeSet == null)
              bsSizeSet = new BitSet();
            String strLabel = viewer.getStandardLabelFormat();
            strings = ArrayUtil.ensureLength(strings, atomIndex + 1);
            strings[atomIndex] = LabelToken.formatLabel(viewer, atom, strLabel);
            formats[atomIndex] = strLabel;
            bsSizeSet.set(atomIndex);
            if ((bsBgColixSet == null || !bsBgColixSet.get(atomIndex))
                && defaultBgcolix != 0)
              setBgcolix(atomIndex, defaultBgcolix);
            mads[atomIndex] = (short) (mode >= 0 ? 1 : -1);
          }
          atom.setShapeVisibility(myVisibilityFlag, strings != null
              && atomIndex < strings.length && strings[atomIndex] != null
              && mads[atomIndex] >= 0);
          //        } else if (strings != null && atomIndex < strings.length) {
          //        strings[atomIndex] = null;         
        }
      }
      return;
    }

    if (propertyName.startsWith("label:")) {
      setLabel(propertyName.substring(6), ((Integer)value).intValue());
      return;
    }

    if (propertyName == "deleteModelAtoms") {
      int firstAtomDeleted = ((int[]) ((Object[]) value)[2])[1];
      int nAtomsDeleted = ((int[]) ((Object[]) value)[2])[2];
      fids = (byte[]) ArrayUtil.deleteElements(fids, firstAtomDeleted,
          nAtomsDeleted);
      bgcolixes = (short[]) ArrayUtil.deleteElements(bgcolixes,
          firstAtomDeleted, nAtomsDeleted);
      offsets = (int[]) ArrayUtil.deleteElements(offsets, firstAtomDeleted,
          nAtomsDeleted);
      formats = (String[]) ArrayUtil.deleteElements(formats, firstAtomDeleted,
          nAtomsDeleted);
      strings = (String[]) ArrayUtil.deleteElements(strings, firstAtomDeleted,
          nAtomsDeleted);
      BitSetUtil.deleteBits(bsFontSet, bsSelected);
      BitSetUtil.deleteBits(bsBgColixSet, bsSelected);
      // pass to super
    }
   
    super.setProperty(propertyName, value, bsSelected);

  }

  private void setLabel(String value, BitSet bsSelected) {
    isActive = true;
    if (bsSizeSet == null)
      bsSizeSet = new BitSet();
    String strLabel = (String) value;
    boolean isScaled = viewer.getFontScaling();
    float scalePixelsPerMicron = (isScaled ? viewer
        .getScalePixelsPerAngstrom(false) * 10000f : 0);
    for (int i = atomCount; --i >= 0;)
      if (bsSelected.get(i))
        setLabel(strLabel, i, isScaled, scalePixelsPerMicron);
  }

  private void setLabel(String value, int i) {
    isActive = true;
    if (bsSizeSet == null)
      bsSizeSet = new BitSet();
    String strLabel = (String) value;
    boolean isScaled = viewer.getFontScaling();
    float scalePixelsPerMicron = (isScaled ? viewer
        .getScalePixelsPerAngstrom(false) * 10000f : 0);
    setLabel(strLabel, i, isScaled, scalePixelsPerMicron);
  }
 
  private void setLabel(String strLabel, int i, boolean isScaled, float scalePixelsPerMicron) {
      Atom atom = atoms[i];
      String label = LabelToken.formatLabel(viewer, atom, strLabel);
      atom.setShapeVisibility(myVisibilityFlag, label != null);
      if (strings == null || i >= strings.length)
        strings = ArrayUtil.ensureLength(strings, i + 1);
      if (formats == null || i >= formats.length)
        formats = ArrayUtil.ensureLength(formats, i + 1);
      strings[i] = label;
      formats[i] = strLabel;
      bsSizeSet.set(i, (strLabel != null));
      text = getLabel(i);
      if (isScaled) {
        text = new Text(g3d, null, label, (short) 0, (short) 0, 0, 0, 0, 0,
            0, scalePixelsPerMicron);
        putLabel(i, text);
      } else if (text != null) {
        text.setText(label);
      }
      if (defaultOffset != zeroOffset)
        setOffsets(i, defaultOffset, false);
      if (defaultAlignment != Object2d.ALIGN_LEFT)
        setAlignment(i, defaultAlignment);
      if ((defaultZPos & FRONT_FLAG) != 0)
        setFront(i, true);
      else if ((defaultZPos & GROUP_FLAG) != 0)
        setGroup(i, true);
      if (defaultPointer != Object2d.POINTER_NONE)
        setPointer(i, defaultPointer);
      if (defaultColix != 0 || defaultPaletteID != 0)
        setColix(i, defaultColix, defaultPaletteID);
      if (defaultBgcolix != 0)
        setBgcolix(i, defaultBgcolix);
      if (defaultFontId != zeroFontId)
        setFont(i, defaultFontId);
}

  public Object getProperty(String property, int index) {
    if (property.equals("offsets"))
      return offsets;
    if (property.equals("defaultState"))
      return getDefaultState();
    if (property.equals("label"))
      return (strings != null && index < strings.length && strings[index] != null
          ? strings[index] : "");
    return null;
  }

  void putLabel(int i, Text text) {
    if (text == null)
      atomLabels.remove(new Integer(i));
    else
      atomLabels.put(new Integer(i), text);
  }

  Text getLabel(int i) {
    return (Text) atomLabels.get(new Integer(i));
  }

  private void setColix(int i, short colix, byte pid) {
    setColixAndPalette(colix, pid, i);
    // text is only created by labelsRenderer
    if (colixes != null && ((text = getLabel(i)) != null))
      text.setColix(colixes[i]);
  }

  private void setBgcolix(int i, short bgcolix) {
    if (bgcolixes == null || i >= bgcolixes.length) {
      if (bgcolix == 0)
        return;
      bgcolixes = ArrayUtil.ensureLength(bgcolixes, i + 1);
    }
    bgcolixes[i] = bgcolix;
    bsBgColixSet.set(i, bgcolix != 0);
    text = getLabel(i);
    if (text != null)
      text.setBgColix(bgcolix);
  }

  final static int POINTER_FLAGS = 0x03;
  final static int ALIGN_FLAGS   = 0x0C;
  final static int ZPOS_FLAGS    = 0x30;
  final static int GROUP_FLAG    = 0x10;
  final static int FRONT_FLAG    = 0x20;
  final static int SCALE_FLAG    = 0x40;
  final static int EXACT_OFFSET_FLAG = 0x80;
  final static int FLAGS         = 0xFF;
  final static int FLAG_OFFSET   = 8;

  private void setOffsets(int i, int offset, boolean isExact) {
    //entry is just xxxxxxxxyyyyyyyy
    //  3         2         1       
    // 10987654321098765432109876543210
    //         xxxxxxxxyyyyyyyytsfgaabp
    //          x-align y-align||||| ||_pointer on
    //                         ||||| |_background pointer color
    //                         |||||_text alignment 0xC
    //                         ||||_labels group 0x10
    //                         |||_labels front  0x20
    //                         ||_scaled
    //                         |_exact offset
    if (offsets == null || i >= offsets.length) {
      if (offset == 0)
        return;
      offsets = ArrayUtil.ensureLength(offsets, i + 1);
    }
    offsets[i] = (offsets[i] & FLAGS) | (offset << FLAG_OFFSET);
    if (isExact)
      offsets[i] |= EXACT_OFFSET_FLAG;
    text = getLabel(i);
    if (text != null)
      text.setOffset(offset);
  }

  private void setAlignment(int i, int alignment) {
    if (offsets == null || i >= offsets.length) {
      if (alignment == Object2d.ALIGN_LEFT)
        return;
      offsets = ArrayUtil.ensureLength(offsets, i + 1);
    }
    offsets[i] = (offsets[i] & ~ALIGN_FLAGS) | (alignment << 2);
    text = getLabel(i);
    if (text != null)
      text.setAlignment(alignment);
  }

  static int getAlignment(int offsetFull) {
    return (offsetFull & ALIGN_FLAGS) >> 2;
  }
 
  private void setPointer(int i, int pointer) {
    if (offsets == null || i >= offsets.length) {
      if (pointer == Object2d.POINTER_NONE)
        return;
      offsets = ArrayUtil.ensureLength(offsets, i + 1);
    }
    offsets[i] = (offsets[i] & ~POINTER_FLAGS) + pointer;
    text = getLabel(i);
    if (text != null)
      text.setPointer(pointer);
  }

  private void setFront(int i, boolean TF) {
    if (offsets == null || i >= offsets.length) {
      if (!TF)
        return;
      offsets = ArrayUtil.ensureLength(offsets, i + 1);
    }
    offsets[i] = (offsets[i] & ~ZPOS_FLAGS) + (TF ? FRONT_FLAG : 0);
  }

  private void setGroup(int i, boolean TF) {
    if (offsets == null || i >= offsets.length) {
      if (!TF)
        return;
      offsets = ArrayUtil.ensureLength(offsets, i + 1);
    }
    offsets[i] = (offsets[i] & ~ZPOS_FLAGS) + (TF ? GROUP_FLAG : 0);
  }

  private void setFont(int i, byte fid) {
    if (fids == null || i >= fids.length) {
      if (fid == zeroFontId)
        return;
      fids = ArrayUtil.ensureLength(fids, i + 1);
    }
    fids[i] = fid;
    bsFontSet.set(i);
    text = getLabel(i);
    if (text != null) {
      text.setFid(fid);
    }
  }

  public void setModelClickability() {
    if (strings == null)
      return;
    for (int i = strings.length; --i >= 0;) {
      String label = strings[i];
      if (label != null && modelSet.atoms.length > i
          && !modelSet.isAtomHidden(i))
        modelSet.atoms[i].setClickable(myVisibilityFlag);
    }
  }

  private String getDefaultState() {
    StringBuffer s = new StringBuffer("\n# label defaults;\n");
    appendCmd(s, "select none");
    appendCmd(s, getColorCommand("label", defaultPaletteID, defaultColix));
    appendCmd(s, "background label " + encodeColor(defaultBgcolix));
    appendCmd(s, "set labelOffset " + Object2d.getXOffset(defaultOffset) + " "
        + (-Object2d.getYOffset(defaultOffset)));
    String align = Object2d.getAlignment(defaultAlignment);
    appendCmd(s, "set labelAlignment " + (align.length() < 5 ? "left" : align));
    String pointer = Object2d.getPointer(defaultPointer);
    appendCmd(s, "set labelPointer " + (pointer.length() == 0 ? "off" : pointer));
    if ((defaultZPos & FRONT_FLAG) != 0)
      appendCmd(s, "set labelFront");
    else if ((defaultZPos & GROUP_FLAG) != 0)
      appendCmd(s, "set labelGroup");
    appendCmd(s, getFontCommand("label", Font3D.getFont3D(defaultFontId)));
    return s.toString();
  }

  public String getShapeState() {
    if (!isActive || bsSizeSet == null)
      return "";
    Hashtable temp = new Hashtable();
    Hashtable temp2 = new Hashtable();
    Hashtable temp3 = new Hashtable();
    for (int i = bsSizeSet.nextSetBit(0); i >= 0; i = bsSizeSet
        .nextSetBit(i + 1)) {
      setStateInfo(temp, i, "label " + Escape.escape(formats[i]));
      if (bsColixSet != null && bsColixSet.get(i))
        setStateInfo(temp2, i, getColorCommand("label", paletteIDs[i],
            colixes[i]));
      if (bsBgColixSet != null && bsBgColixSet.get(i))
        setStateInfo(temp2, i, "background label " + encodeColor(bgcolixes[i]));
      Text text = getLabel(i);
      float sppm = (text != null ? text.getScalePixelsPerMicron() : 0);
      if (sppm > 0)
        setStateInfo(temp2, i, "set labelScaleReference " + (10000f / sppm));
      if (offsets != null && offsets.length > i) {
        int offsetFull = offsets[i];
        setStateInfo(
            temp2,
            i,
            "set "
                + ((offsetFull & EXACT_OFFSET_FLAG) == EXACT_OFFSET_FLAG ? "labelOffsetExact "
                    : "labelOffset ")
                + Object2d.getXOffset(offsetFull >> FLAG_OFFSET) + " "
                + (-Object2d.getYOffset(offsetFull >> FLAG_OFFSET)));
        String align = Object2d.getAlignment(offsetFull >> 2);
        String pointer = Object2d.getPointer(offsetFull);
        if (pointer.length() > 0)
          setStateInfo(temp2, i, "set labelPointer " + pointer);
        if ((offsetFull & FRONT_FLAG) != 0)
          setStateInfo(temp2, i, "set labelFront");
        else if ((offsetFull & GROUP_FLAG) != 0)
          setStateInfo(temp2, i, "set labelGroup");
        // labelAlignment must come last, so we put it in a separate hash
        // table
        if (align.length() > 0)
          setStateInfo(temp3, i, "set labelAlignment " + align);
      }
      if (mads != null && mads[i] < 0)
        setStateInfo(temp2, i, "set toggleLabel");
      if (bsFontSet != null && bsFontSet.get(i))
        setStateInfo(temp2, i, getFontCommand("label", Font3D
            .getFont3D(fids[i])));
    }
    return getShapeCommands(temp, temp2)
        + getShapeCommands(null, temp3);
  }

  int pickedAtom = -1;
  int pickedOffset = 0;
  public synchronized boolean checkObjectDragged(int prevX, int prevY, int x,
                                                 int y, int modifiers,
                                                 BitSet bsVisible) {
    if (viewer.getPickingMode() != ActionManager.PICKING_LABEL)
      return false;
    // mouse down ?
    if (prevX == Integer.MIN_VALUE) {
      int iAtom = viewer.findNearestAtomIndex(x, y);
      if (iAtom >= 0 && atoms[iAtom].isVisible(myVisibilityFlag)) {
        pickedAtom = iAtom;
        pickedOffset = (offsets == null
            || pickedAtom >= offsets.length ? 0
                : offsets[pickedAtom]) >> FLAG_OFFSET;
        return true;
      }
      return false;
    }
    // mouse up ?
    if (prevX == Integer.MAX_VALUE) {
      pickedAtom = -1;
      return false;
    }
    if (pickedAtom < 0)
      return false;
    move2D(pickedAtom, x, y);
    return true;
  }
                        
  private void move2D(int pickedAtom, int x, int y) {
    if (g3d.isAntialiased()) {
      x <<= 1;
      y <<= 1;
    }
    Atom atom = atoms[pickedAtom];
    int xOffset = Object2d.getXOffset(pickedOffset);
    int yOffset = -Object2d.getYOffset(pickedOffset);
    xOffset += x - atom.screenX;
    yOffset += atom.screenY - y;
    int offset = Object2d.getOffset(xOffset, yOffset);
    if (offset == 0)
      offset = Short.MAX_VALUE;
    else if (offset == zeroOffset)
      offset = 0;
    setOffsets(pickedAtom, offset, true);
  }
 
}
TOP

Related Classes of org.jmol.shape.Labels

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.