Package com.google.gwt.dev

Source Code of com.google.gwt.dev.ModuleTabPanel

/*
* Copyright 2009 Google Inc.
*
* 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.google.gwt.dev;

import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.dev.SwingUI.TabPanelCollection;
import com.google.gwt.dev.shell.WrapLayout;
import com.google.gwt.dev.util.BrowserInfo;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

/**
* A panel which contains all modules in one browser tab.
*/
public class ModuleTabPanel extends JPanel {

  /**
   * A session has a unique session key within a module tab panel, and is
   * identified to the user by the timestamp it was first seen.
   *
   * <p>Within a session, there will be one or more modules, each with their
   * own ModulePanel.
   */
  public class Session {

    private final long createTimestamp;

    /**
     * Map from display names in the dropdown box to module panels.
     */
    private final Map<String, ModulePanel> displayNameToModule;

    private final IdentityHashMap<ModulePanel, SessionModule> moduleSessionMap;

    private SessionModule lastSelectedModule;

    /**
     * Map of module names to the number of times that module has been seen.
     */
    private final Map<String, Integer> moduleCounts;

    /**
     * List, in display order, of entries in the module dropdown box.
     */
    private final List<SessionModule> modules;

    private final String sessionKey;

    public Session(String sessionKey) {
      this.sessionKey = sessionKey;
      createTimestamp = System.currentTimeMillis();
      displayNameToModule = new HashMap<String, ModulePanel>();
      moduleSessionMap = new IdentityHashMap<ModulePanel, SessionModule>();
      modules = new ArrayList<SessionModule>();
      moduleCounts = new HashMap<String, Integer>();
    }

    public synchronized void addModule(String moduleName,
        ModulePanel panel) {
      Integer moduleCount = moduleCounts.get(moduleName);
      if (moduleCount == null) {
        moduleCount = 0;
      }
      moduleCounts.put(moduleName, moduleCount + 1);
      String shortModuleName = getShortModuleName(moduleName);
      if (moduleCount > 0) {
        shortModuleName += " (" + moduleCount + ")";
      }
      SessionModule sessionModule = SessionModule.create(sessionKey,
          panel, shortModuleName);
      modules.add(sessionModule);
      displayNameToModule.put(shortModuleName, panel);
      moduleSessionMap.put(panel, sessionModule);
      // add this item with the key we will use with cardLayout later
      deckPanel.add(panel, sessionModule.getStringKey());
      if (this == currentSession) {
        moduleDropdown.addItem(sessionModule);
        if (moduleDropdown.getItemCount() > 1) {
          moduleDropdownPanel.setEnabled(true);
          moduleDropdownPanel.setVisible(true);
        }
        selectModule(sessionModule);
      }
    }

    public void buildModuleDropdownContents() {
      if (this == currentSession) {
        moduleDropdown.removeAllItems();
        SessionModule firstModule = null;
        for (SessionModule sessionModule : modules) {
         moduleDropdown.addItem(sessionModule);
          if (firstModule == null) {
            firstModule = sessionModule;
          }
        }
        if (moduleDropdown.getItemCount() > 1) {
          moduleDropdownPanel.setEnabled(true);
          moduleDropdownPanel.setVisible(true);
        } else {
          moduleDropdownPanel.setEnabled(false);
          moduleDropdownPanel.setVisible(false);
        }
        if (lastSelectedModule != null) {
          selectModule(lastSelectedModule);
        } else if (firstModule != null) {
          selectModule(firstModule);
        }
      }
    }

    public void disconnectModule(ModulePanel modulePanel) {
      /*
       * TODO(jat): for now, only disconnected modules can be closed.  When
       *     SWT is ripped out and we can pass OOPHM-specific classes through
       *     BrowseWidgetHost.createModuleSpaceHost, we will need to be able
       *     to shutdown the connection from here if it is not already
       *     disconnected.
       */
      SessionModule sessionModule = moduleSessionMap.get(modulePanel);
      moduleSessionMap.remove(modulePanel);
      deckPanel.remove(modulePanel);
      modules.remove(sessionModule);
      switch (modules.size()) {
        case 0: // we just closed the last module in this session
          closeSession(this);
          break;
        case 1: // only one module left, hide dropdown
          moduleDropdownPanel.setEnabled(false);
          moduleDropdownPanel.setVisible(false);
          break;
        default:
          if (lastSelectedModule == sessionModule) {
            // if we closed the active module, switch to the most recent remaining
            lastSelectedModule = modules.get(modules.size() - 1);
          }
          buildModuleDropdownContents();
          break;
      }
    }

    public Collection<String> getActiveModules() {
      ArrayList<String> activeModules = new ArrayList<String>();
      for (SessionModule sessionModule : modules) {
        String displayName = sessionModule.toString();
        Disconnectable module = sessionModule.getModulePanel();
        if (!module.isDisconnected()) {
          activeModules.add(displayName);
        }
      }
      return Collections.unmodifiableList(activeModules);
    }

    public String getDisplayName() {
      return DateFormat.getDateTimeInstance().format(new Date(createTimestamp));
    }

    public String getSessionKey() {
      return sessionKey;
    }

    public boolean hasActiveModules() {
      for (SessionModule sessionModule : modules) {
        Disconnectable module = sessionModule.getModulePanel();
        if (!module.isDisconnected()) {
          return true;
        }
      }
      return false;
    }

    @Override
    public String toString() {
      return getDisplayName();
    }

    private String getShortModuleName(String moduleName) {
      int idx = moduleName.lastIndexOf('.');
      if (idx < 0) {
        return moduleName;
      } else {
        return moduleName.substring(idx + 1);
      }
    }

    private void selectModule(SessionModule sessionModule) {
      cardLayout.show(deckPanel, sessionModule.getStringKey());
      lastSelectedModule = sessionModule;
      moduleDropdown.setSelectedItem(sessionModule);
    }
  }

  /**
   * Renderer used to show entries in the module dropdown box.
   */
  private static class SessionModuleRenderer extends BasicComboBoxRenderer {

    @Override
    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus) {
      // the superclass just returns this, so we don't save the result and
      // cast it back to a label
      super.getListCellRendererComponent(list, value, index,
          isSelected, cellHasFocus);
      if (value instanceof SessionModule) {
        SessionModule sessionModule = (SessionModule) value;
        if (sessionModule.getModulePanel().isDisconnected()) {
          setForeground(DISCONNECTED_DROPDOWN_COLOR);
          setFont(getFont().deriveFont(Font.ITALIC));
        }
        // TODO(jat): set font to bold/etc if the window has new messages
      }
      return this;
    }
  }

  /**
   * Renderer used to show entries in the session dropdown box.
   */
  private static class SessionRenderer extends BasicComboBoxRenderer {

    @Override
    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus) {
      // the superclass just returns this, so we don't save the result and
      // cast it back to a label
      super.getListCellRendererComponent(list, value, index,
          isSelected, cellHasFocus);
      if (value instanceof Session) {
        Session session = (Session) value;
        if (!session.hasActiveModules()) {
          setForeground(DISCONNECTED_DROPDOWN_COLOR);
          setFont(getFont().deriveFont(Font.ITALIC));
        }
        // TODO(jat): set font to bold/etc if new modules were added
      }
      return this;
    }
  }

  public static final Color DISCONNECTED_DROPDOWN_COLOR = Color.decode("0x808080");

  private CardLayout cardLayout;

  private Session currentSession;

  private JPanel deckPanel;

  private JComboBox moduleDropdown;

  private JComboBox sessionDropdown;

  private final Map<String, Session> sessions = new HashMap<String, Session>();

  private final TabPanelCollection tabPanelCollection;

  private JPanel topPanel;

  private JPanel sessionDropdownPanel;

  private JPanel moduleDropdownPanel;

  /**
   * Create a panel which will be a top-level tab in the OOPHM UI.  Each of
   * these tabs will contain one or more sessions, and within that one or
   * more module instances.
   *
   * @param userAgent
   * @param remoteSocket
   * @param url
   * @param agentIconBytes
   * @param tabPanelCollection
   * @param moduleName used just for the tab name in the event that the plugin
   *     is an older version that doesn't supply the url
   */
  public ModuleTabPanel(String userAgent, String remoteSocket, String url,
      byte[] agentIconBytes, TabPanelCollection tabPanelCollection,
      String moduleName) {
    super(new BorderLayout());
    this.tabPanelCollection = tabPanelCollection;
    topPanel = new JPanel();
    sessionDropdownPanel = new JPanel(new WrapLayout());
    sessionDropdownPanel.add(new JLabel("Session: "));
    sessionDropdown = new JComboBox();
    sessionDropdown.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        Session session = (Session) sessionDropdown.getSelectedItem();
        selectSession(session);
      }

    });
    sessionDropdown.setRenderer(new SessionRenderer());
    sessionDropdownPanel.add(sessionDropdown);
    sessionDropdownPanel.setEnabled(false);
    sessionDropdownPanel.setVisible(false);
    topPanel.add(sessionDropdownPanel);
    moduleDropdownPanel = new JPanel(new WrapLayout());
    moduleDropdownPanel.add(new JLabel("Module: "));
    moduleDropdown = new JComboBox();
    moduleDropdown.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        SessionModule sessionModule = (SessionModule)
            moduleDropdown.getSelectedItem();
        if (sessionModule != null) {
          // may be null when removeAllItems is called
          currentSession.selectModule(sessionModule);
        }
      }
    });
    moduleDropdown.setRenderer(new SessionModuleRenderer());
    moduleDropdownPanel.add(moduleDropdown);
    moduleDropdownPanel.setEnabled(false);
    moduleDropdownPanel.setVisible(false);
    topPanel.add(moduleDropdownPanel);
    add(topPanel, BorderLayout.NORTH);
    cardLayout = new CardLayout();
    deckPanel = new JPanel(cardLayout);
    add(deckPanel);

    // Construct the tab title and tooltip
    String tabTitle = url;
    if (tabTitle == null) {
      int idx = moduleName.lastIndexOf('.');
      tabTitle = moduleName.substring(idx + 1);
      url = "";
    } else {
      try {
        URL parsedUrl = new URL(url);
        tabTitle = getTabTitle(parsedUrl);
        // rebuild the URL omitting query params and the hash
        StringBuilder buf = new StringBuilder();
        buf.append(parsedUrl.getProtocol()).append(':');
        if (parsedUrl.getAuthority() != null
            && parsedUrl.getAuthority().length() > 0) {
          buf.append("//").append(parsedUrl.getAuthority());
        }
        if (parsedUrl.getPath() != null) {
          buf.append(parsedUrl.getPath());
        }
        buf.append(' '); // space for tooltip below
        url = buf.toString();
      } catch (MalformedURLException e1) {
        // Ignore and just use the full URL
      }
    }

    ImageIcon browserIcon = null;
    if (agentIconBytes != null) {
      browserIcon = new ImageIcon(agentIconBytes);
    }
    String shortName = BrowserInfo.getShortName(userAgent);
    if (browserIcon == null) {
      if (shortName != null) {
        tabTitle += " (" + shortName + ")";
      }
    }
    tabPanelCollection.addTab(this, browserIcon, tabTitle, url + "from "
        + remoteSocket + " on " + userAgent);
  }

  public synchronized ModulePanel addModuleSession(Type maxLevel,
      String moduleName,
      String sessionKey,
      File logFile) {
    Session session = findOrCreateSession(sessionKey);

    ModulePanel panel = new ModulePanel(maxLevel, moduleName, session, logFile);
    return panel;
  }

  private synchronized void addSession(Session session) {
    sessionDropdown.addItem(session);
    sessionDropdown.setSelectedItem(session);
    if (sessionDropdown.getItemCount() > 1) {
      sessionDropdownPanel.setEnabled(true);
      sessionDropdownPanel.setVisible(true);
    }
    selectSession(session);
  }

  private synchronized void closeSession(Session session) {
    sessionDropdown.removeItem(session);
    sessions.remove(session.getSessionKey());
    switch (sessionDropdown.getItemCount()) {
      case 0: // last session closed, close tab
        tabPanelCollection.removeTab(this);
        return;
      case 1: // one session left, remove dropdown
        sessionDropdownPanel.setEnabled(false);
        sessionDropdownPanel.setVisible(false);
        break;
      default: // more than 1 left, do nothing
        break;
    }
    if (session == currentSession) {
      selectSession((Session) sessionDropdown.getItemAt(
          sessionDropdown.getItemCount() - 1));
    }
  }

  /**
   * Return the proper Session object for this session, creating it if needed.
   *
   * @param sessionKey unique key for this session
   * @return Session instance
   */
  private synchronized Session findOrCreateSession(String sessionKey) {
    Session session = sessions.get(sessionKey);
    if (session == null) {
      session = new Session(sessionKey);
      sessions.put(sessionKey, session);
      addSession(session);
    }
    return session;
  }

  private String getTabTitle(URL parsedUrl) {
    String tabTitle = parsedUrl.getPath();
    if (tabTitle.length() > 0) {
      int startIdx = tabTitle.lastIndexOf('/');
      int lastIdx = tabTitle.length();
      if (tabTitle.endsWith(".html")) {
        lastIdx -= 5;
      } else if (tabTitle.endsWith(".htm")) {
        lastIdx -= 4;
      }
      tabTitle = tabTitle.substring(startIdx + 1, lastIdx);
    } else {
      tabTitle = "/";
    }
    return tabTitle;
  }

  private void selectSession(Session session) {
    currentSession = session;
    if (session != null) {
      // can be null when last session removed
      session.buildModuleDropdownContents();
    }
  }
}
TOP

Related Classes of com.google.gwt.dev.ModuleTabPanel

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.