package jimmui.view.roster; import jimm.Jimm; import jimm.Options; import jimm.comm.StringUtils; import jimm.comm.Util; import jimm.modules.*; import jimmui.HotKeys; import jimmui.model.chat.ChatModel; import jimmui.updater.RosterUpdater; import jimmui.view.base.*; import jimmui.view.base.touch.*; import jimmui.view.icons.Icon; import jimmui.view.roster.items.*; import protocol.Contact; import protocol.Group; import protocol.Protocol; import protocol.ui.InfoFactory; import protocol.ui.StatusInfo; import protocol.ui.XStatusInfo; import javax.microedition.lcdui.Font; import javax.microedition.lcdui.Graphics; import java.util.Vector; /** * Created with IntelliJ IDEA. * <p/> * Date: 24.07.13 20:13 * * @author vladimir */ public class RosterContent extends SomeContent { private Vector drawItems = new Vector(); private int itemHeight = 0; private ContactListListener clListener; private Icon[] leftIcons = new Icon[5]; private Icon[] rightIcons = new Icon[1]; private int stepSize; private int nodeRectHeight; private boolean showStatusLine; private ContactListModel model; private RosterUpdater updater = new RosterUpdater(); private boolean rebuildList; private TreeNode currentNode = null; private Vector<TreeNode>[] listOfContactList = new Vector[]{new Vector<TreeNode>(), new Vector<TreeNode>()}; private int visibleListIndex = 0; public RosterContent(SomeContentList view) { super(view); } @Override public int getSize() { return drawItems.size(); } @Override public int getItemHeight(int itemIndex) { return itemHeight; } @Override public void doJimmAction(int keyCode) { TreeNode item = getCurrentNode(); updater.setCurrentContact((item instanceof Contact) ? (Contact)item : null); switch (keyCode) { case NativeCanvas.JIMM_SELECT: itemSelected(getCurrentNode()); break; case NativeCanvas.JIMM_MENU: clListener.activateMainMenu(); break; case NativeCanvas.JIMM_BACK: if (getModel() == getUpdater().getChatModel()) { ((VirtualContactList)view).setModel(getUpdater().getModel()); view.back(); } else { showContextMenu(getCurrentNode()); } break; } } @Override protected boolean doKeyReaction(int keyCode, int actionCode, int type) { TreeNode item = getCurrentNode(); Contact current = (item instanceof Contact) ? (Contact)item : null; if (CanvasEx.KEY_PRESSED == type) { updater.setCurrentContact(current); switch (keyCode) { case NativeCanvas.CLEAR_KEY: if ((item instanceof Contact) && ((Contact)item).hasChat()) { ChatModel chat = Jimm.getJimm().jimmModel.getChatModel((Contact)item); Jimm.getJimm().getChatUpdater().removeReadMessages(chat); } return true; } } Protocol p = getProtocol(item); return HotKeys.execHotKey(p, current, keyCode, type) || super.doKeyReaction(keyCode, actionCode, type); } @Override public void drawItemBack(GraphicsEx g, int index, int current, int x, int y, int w, int h, int skip, int to) { TreeNode node = getDrawItem(index); if (node instanceof ProtocolBranch) { if (current == index) { g.setThemeColor(CanvasEx.THEME_SELECTION_BACK, CanvasEx.THEME_PROTOCOL_BACK, 0xA0); } else { g.setThemeColor(CanvasEx.THEME_PROTOCOL_BACK); } byte progress = ((ProtocolBranch)node).getProtocol().getConnectingProgress(); int width = w + x - x + 4; if (progress < 100) { width = width * progress / 100; } g.fillRect(x - 2, y, width, h); } } @Override protected void drawItemData(GraphicsEx g, int index, int x1, int y1, int w, int h, int skip, int to) { TreeNode node = getDrawItem(index); for (int i = 0; i < leftIcons.length; ++i) { leftIcons[i] = null; } rightIcons[0] = null; node.getLeftIcons(leftIcons); node.getRightIcons(rightIcons); int x = x1; if (node instanceof ProtocolBranch) { g.setThemeColor(CanvasEx.THEME_PROTOCOL); g.setFont(getFontSet()[CanvasEx.FONT_STYLE_PLAIN]); drawNodeRect(g, (TreeBranch)node, x, y1, y1 + h); x += nodeRectHeight + 2; g.drawString(leftIcons, node.getText(), rightIcons, x, y1, w + x1 - x, h); return; } if (model.hasGroups()) { if (node instanceof GroupBranch) { g.setThemeColor(CanvasEx.THEME_GROUP); g.setFont(getFontSet()[CanvasEx.FONT_STYLE_PLAIN]); drawNodeRect(g, (GroupBranch)node, x, y1, y1 + h); x += nodeRectHeight + 2; g.drawString(leftIcons, node.getText(), rightIcons, x, y1, w + x1 - x, h); return; } x += stepSize; } drawContact(g, (Contact)node, x, y1, w + x1 - x, h); } /** draw + or - before node text */ private void drawNodeRect(GraphicsEx g, TreeBranch branch, int x, int y1, int y2) { int height = nodeRectHeight; final int half = (height + 1) / 2; final int quarter = (half + 1) / 2; int y = (y1 + y2 - height) / 2; if (branch.isEmpty()) { x += quarter; g.drawLine(x, y, x, y + height); while (0 < height) { g.drawLine(x, y, x, y + 1); g.drawLine(x, y + height - 1, x, y + height); height -= 2; y += 1; x += 1; } return; } if (branch.isExpanded()) { y += quarter; while (0 < height) { g.drawLine(x, y, x + height, y); height -= 2; y += 1; x += 1; } } else { x += quarter; while (0 < height) { g.drawLine(x, y, x, y + height); height -= 2; y += 1; x += 1; } } } private void drawContact(GraphicsEx g, Contact c, int x, int y, int w, int h) { g.setThemeColor(getContactTheme(c)); if (!showStatusLine) { g.setFont(getFontSet()[c.hasChat() ? CanvasEx.FONT_STYLE_BOLD : CanvasEx.FONT_STYLE_PLAIN]); g.drawString(leftIcons, c.getName(), rightIcons, x, y, w, h); return; } int lWidth = g.drawImages(leftIcons, x, y, h); if (lWidth > 0) { lWidth++; } int rWidth = g.getImagesWidth(rightIcons); if (rWidth > 0) { rWidth++; } g.drawImages(rightIcons, x + w - rWidth, y, h); w -= lWidth + rWidth; x += lWidth; g.setClip(x, y, w, h); Font contactFont = getFontSet()[c.hasChat() ? CanvasEx.FONT_STYLE_BOLD : CanvasEx.FONT_STYLE_PLAIN]; Font statusFont = GraphicsEx.statusLineFont; int statusHeight = statusFont.getHeight(); y += (h - (contactFont.getHeight() + statusHeight)) / 2; g.setFont(contactFont); g.drawString(c.getName(), x, y, Graphics.LEFT + Graphics.TOP); g.setFont(statusFont); g.setThemeColor(CanvasEx.THEME_CONTACT_STATUS); g.drawString(getStatusMessage(c), x, y + statusHeight, Graphics.LEFT + Graphics.TOP); } private byte getContactTheme(Contact c) { if (c.isTemp()) { return CanvasEx.THEME_CONTACT_TEMP; } if (c.hasChat()) { return CanvasEx.THEME_CONTACT_WITH_CHAT; } if (c.isOnline()) { return CanvasEx.THEME_CONTACT_ONLINE; } return CanvasEx.THEME_CONTACT_OFFLINE; } private Font[] getFontSet() { return GraphicsEx.contactListFontSet; } private String getStatusMessage(Contact contact) { String message; Protocol protocol = getProtocol(contact); // #sijapp cond.if modules_XSTATUSES is "true" # if (XStatusInfo.XSTATUS_NONE != contact.getXStatusIndex()) { message = contact.getXStatusText(); if (!StringUtils.isEmpty(message)) { return message; } message = InfoFactory.factory.getXStatusInfo(protocol).getName(contact.getXStatusIndex()); if (!StringUtils.isEmpty(message)) { return message; } } // #sijapp cond.end # message = contact.getStatusText(); if (!StringUtils.isEmpty(message)) { return message; } return InfoFactory.factory.getStatusInfo(protocol).getName(contact.getStatusIndex()); } public ContactListModel getModel() { return model; } public void setCLListener(ContactListListener listener) { clListener = listener; } public void setModel(ContactListModel model) { this.model = model; update(); } public RosterUpdater getUpdater() { return updater; } private void showContextMenu(TreeNode item) { Protocol p = getProtocol(item); if ((null == item) || p.isConnecting()) { if (!(item instanceof ProtocolBranch)) { return; } } view.showMenu(this.clListener.getContextMenu(p, item)); } private Protocol getProtocol(TreeNode node) { if (node instanceof ProtocolBranch) { return ((ProtocolBranch)node).getProtocol(); } if (node instanceof Contact) { return model.getContactProtocol((Contact) node); } Protocol last = null; for (int i = 0; i < drawItems.size(); ++i) { if (drawItems.elementAt(i) instanceof ProtocolBranch) { last = ((ProtocolBranch)drawItems.elementAt(i)).getProtocol(); } else if (drawItems.elementAt(i) == node) { return last; } } return model.getProtocol(0); } public final Protocol getCurrentProtocol() { Protocol protocol = getProtocol(getCurrentNode()); if ((null != protocol) && (null == protocol.getProfile())) { protocol = model.getProtocol(0); } return protocol; } private TreeNode getCurrentNode() { return getSafeNode(getCurrItem()); } private TreeNode getSafeNode(int index) { if ((index < drawItems.size()) && (index >= 0)) { return getDrawItem(index); } return null; } private TreeNode getDrawItem(int index) { return (TreeNode) drawItems.elementAt(index); } private void updateTree() { rebuildList = true; invalidate(); } /** * Set node as current. Make autoscroll if needs. */ private void setCurrentNode(TreeNode node) { if (null != node) { currentNode = node; } } /** * Expand or collapse tree node. * NOTE: this is not recursive operation! */ private void setExpandFlag(TreeBranch node, boolean value) { setCurrentNode(getCurrentNode()); node.setExpandFlag(value); updateTree(); } private void itemSelected(TreeNode item) { if (null == item) { return; } if (item instanceof Contact) { ((Contact)item).activate(model.getContactProtocol((Contact)item)); } else if (item instanceof GroupBranch) { GroupBranch group = (GroupBranch)item; setExpandFlag(group, !group.isExpanded()); } else if (item instanceof TreeBranch) { TreeBranch root = (TreeBranch)item; setExpandFlag(root, !root.isExpanded()); } } // #sijapp cond.if modules_TOUCH is "true"# @Override protected void touchItemTaped(int item, int x, TouchState state) { int itemHeight = getItemHeight(item); TreeNode currentNode = getSafeNode(item); if (state.isLong || (view.getWidth() - itemHeight < x)) { showContextMenu(currentNode); } else if (state.isSecondTap) { itemSelected(currentNode); } } // #sijapp cond.end# public void updateOption() { showStatusLine = Options.getBoolean(Options.OPTION_SHOW_STATUS_LINE); stepSize = Math.max(getFontSet()[CanvasEx.FONT_STYLE_PLAIN].getHeight() / 4, 2); model.hideOffline = Options.getBoolean(Options.OPTION_CL_HIDE_OFFLINE); } public void buildList() { TreeNode current = currentNode; currentNode = null; int prevIndex = getCurrItem(); if (null != current) { expandNodePath(current); } else { current = getSafeNode(prevIndex); } visibleListIndex ^= 1; Vector<TreeNode> items = listOfContactList[visibleListIndex]; items.removeAllElements(); model.buildFlatItems(items); drawItems = items; if (null != current) { int currentIndex = Util.getIndex(items, current); if ((prevIndex != currentIndex) && (-1 != currentIndex)) { setCurrentItemIndex(currentIndex); } } if (items.size() <= getCurrItem()) { setCurrentItemIndex(0); } //if (0 == model.getProtocolCount()) { // setMessage(ResourceBundle.getString("No accounts")); //} listOfContactList[visibleListIndex ^ 1].removeAllElements(); } /** * Build path to node int tree. */ private void expandNodePath(TreeNode node) { if ((node instanceof Contact) && model.hasGroups()) { Contact c = (Contact)node; Protocol p = model.getContactProtocol(c); if (null != p) { Group group = p.getGroupById(c.getGroupId()); model.expandPath(new RosterUpdater.Update(p, group, c, RosterUpdater.Update.EXPAND)); } } } public void setActiveContact(Contact cItem) { setCurrentNode(cItem); updateTree(); } void updateItemHeight() { int iconHeight = 0; if (0 < getModel().getProtocolCount()) { Protocol p = getModel().getProtocol(0); Icon icon = InfoFactory.factory.getStatusInfo(p).getIcon(StatusInfo.STATUS_ONLINE); iconHeight = (null == icon) ? 0 : (icon.getHeight() + 2); } int fontHeight = GraphicsEx.contactListFontSet[CanvasEx.FONT_STYLE_PLAIN].getHeight(); if (showStatusLine) { fontHeight += GraphicsEx.statusLineFont.getHeight(); } itemHeight = Math.max(Math.max(iconHeight, fontHeight), CanvasEx.minItemHeight); nodeRectHeight = Math.max(itemHeight / 2, 7); if (0 == (nodeRectHeight & 1)) { nodeRectHeight--; } } public void update() { rebuildList = true; } @Override protected void updateTask(long microTime) { if (rebuildList) { invalidate(); } } protected void beforePaint() { if (rebuildList) { rebuildList = false; updater.updateTree(); try { buildList(); updateItemHeight(); } catch (Exception e) { // #sijapp cond.if modules_DEBUGLOG is "true" # DebugLog.panic("update ", e); // #sijapp cond.end # } } } }