protected void deleteCurrent() { int num_logs_deleted = 0; Set<Group> groups_changed = new HashSet<>(); for (TreePath tp : display.logTree.getSelectionPaths()) { if (tp.getPathCount() == 3) { Group group = (Group) tp.getPath()[1]; LogReference reference = (LogReference) tp.getLastPathComponent(); Debug.warn("deleting {%s} from {%s}", reference, group); group.remove(reference); ++num_logs_deleted; groups_changed.add(group); } else { Debug.warn("cannot delete {%s}", tp.getLastPathComponent()); } } for (Group group : groups_changed) { TreeModelEvent removeEvent = new TreeModelEvent(this, new Object[] {this, group}); for (TreeModelListener listener : listeners) listener.treeStructureChanged(removeEvent); } ToolMessage.displayAndPrint("deleted %d logs", num_logs_deleted); }
private void controlConnectAction() { if (robot == null) { assert (display.connectButton.getText().equals("connect")); } else { assert (display.connectButton.getText().equals("disconnect")); Debug.info("trying to kill %s", robot); final RobotConnection _robot = robot; Center.addEvent( new Center.EventRunnable() { @Override protected void run() { _robot.kill(); } }); return; } String address = (String) display.robotAddressBox.getSelectedItem(); if (address == null) { ToolMessage.displayError("choose valid address"); return; } address = address.trim(); if (display.localCheckBox.isSelected() && !address.endsWith(".local")) { address += ".local"; } display.connectButton.setEnabled(false); Center.addEvent(new ControlConnectRunnable(address)); }
@Override public void ioReceived(IOInstance inst, int ret, Log... out) { if (inst == robot) { // Deal with streaming... LogSearching.Criteria criteria = LogSearching.criteriaAt(display.streamComboBox.getSelectedIndex()); if (criteria != null) { Log pass = null; for (Log l : out) { if (criteria.fits(l.getFullDescription())) pass = l; } if (pass != null) displayLog(pass); } // Deal with adding to groups (i.e. keeping)... assert (lastGroup != null); for (Log l : out) { if (shouldKeep(l.jvm_unique_id)) lastGroup.add(LogReference.referenceFromLog(l)); } Events.GLogsFound.generate(this, out); } else { Debug.error("%s got %d surprising logs from %s", this, out.length, inst); } }
@Override public void actionPerformed(ActionEvent e) { String suggest = null; if (group.source == Group.GroupSource.ROBOT_STREAM) { String rname = null; boolean same = true; for (LogReference ref : group.logs) { if (rname == null) { rname = ref.host_name; } else { if (!rname.equals(ref.host_name)) { same = false; break; } } } suggest = (same && rname != null) ? PathChooser.suggestion(rname) : null; } Path path = PathChooser.chooseDirPath(this, suggest); if (path != null) { for (LogReference ref : group.logs) { Debug.info("writing log r%d to %s", ref.thisID, path); ref.copyLogToPath(path); } } }
private void controlLoadAction() { if (robot == null) { Path selected = (Path) display.pathBox.getSelectedItem(); if (selected == null) { Debug.error("null path"); ToolMessage.display("load action: null path", Color.RED); return; } if (FileIO.isValidLogFolder(selected)) { updateComboBoxAndSettings(display.pathBox, UserSettings.loadPathes, selected); lastGroup = Group.groupFromPath(selected); LogReference[] added; try { added = FileIO.readAllRefsFromPath(selected, true); } catch (Throwable e) { ToolMessage.displayError( "error {%s} (see below) reading Log refs from %s", e.getMessage(), selected); e.printStackTrace(); return; } lastGroup.add(added); // Log[] addedLogs = new Log[added.length]; // for (int i = 0; i < added.length; ++i) // addedLogs[i] = added[i].get(); ToolMessage.displayInfo("loaded %d logs into %s", added.length, lastGroup); Events.GGroupAdded.generate(this, lastGroup); Events.GLogRefsFound.generate(this, added); // Events.GLogsFound.generate(this, addedLogs); display.leftSideTabs.setSelectedComponent(display.logTab); } else { Debug.error("invalid Log folder: " + selected.toString()); ToolMessage.display("invalid Log folder: " + selected.toString(), Color.RED); return; } } else { Debug.error("cannot load session while streaming (%s)", robot); ToolMessage.display("cannot load session while streaming", Color.ORANGE); } }
protected void showReferenceAdded(LogReference reference) { Debug.event("LogModel reference added"); TreeModelEvent tme = new TreeModelEvent(this, new Object[] {this, reference.container}); for (TreeModelListener l : listeners) { l.treeStructureChanged(tme); } }
protected void treeReSorted() { Debug.event("LogModel tree resorted"); TreeModelEvent tme = new TreeModelEvent(this, new Object[] {this}); for (TreeModelListener l : listeners) { l.treeStructureChanged(tme); } }
protected void showGroupAdded(Group group) { // TreeModelEvent tme = new TreeModelEvent(this, new Object[]{root}, // new int[]{AllGroups.allGroups.indexOf(group)}, // new Object[]{group}); Debug.event("LogModel group added"); TreeModelEvent changed = new TreeModelEvent(this, new Object[] {this}); for (TreeModelListener listener : listeners) listener.treeStructureChanged(changed); }
@Override public void valueChanged(TreeSelectionEvent e) { if (!e.isAddedPath()) { // path unselected, ignore return; } TreePath[] selected = display.logTree.getSelectionPaths(); switch (selected[0].getPathCount()) { case 0: Debug.error("null selection!"); break; case 1: Debug.error("root selected!"); break; case 2: { Group group = (Group) selected[0].getLastPathComponent(); displayGroup(group); Events.GGroupSelected.generate(this, group); } return; case 3: { List<Log> all = new LinkedList<>(); for (TreePath path : selected) { if (path.getPathCount() != 3) continue; // it isn't a Log selection LogReference ref = (LogReference) path.getLastPathComponent(); all.add(ref.get()); } Log first = all.remove(0); displayLog(first, all); Events.GLogSelected.generate(outerClassThis, first, all); } return; default: Debug.error( "selection count %d %s", selected[0].getPathCount(), selected[0].getLastPathComponent()); } }
@Override public int getIndexOfChild(Object parent, Object child) { if (parent == this) { return AllGroups.allGroups.indexOf(child); } else if (parent instanceof Group) { return currentlyDisplayedFrom((Group) parent).indexOf(child); } else { Debug.error("parent %s not container!", parent); return -1; } }
@Override public void ioFinished(IOInstance instance) { if (instance == robot) { ToolMessage.displayWarn("robot %s disconnected!", instance); display.rpcScrollPane.setViewportView(new JLabel("no connection")); display.connectButton.setText("connect"); display.loadButton.setEnabled(true); robot = null; } else { Debug.error("informed of dead connection %s but robot=%s", instance, robot); } }
@Override protected void run() { Debug.warn("trying to connect to %s", robotAddress); robot = RobotConnection.connectToRobot(robotAddress, outerThis); if (robot == null) { ToolMessage.displayError("connection failed to: %s", robotAddress); SwingUtilities.invokeLater( new Runnable() { @Override public void run() { display.connectButton.setEnabled(true); } }); return; } else { ToolMessage.displayWarn("SUCCESS: connected to %s (%s)", robotAddress, robot); SwingUtilities.invokeLater( new Runnable() { @Override public void run() { display.connectButton.setEnabled(true); display.connectButton.setText("disconnect"); display.loadButton.setEnabled(false); updateComboBoxAndSettings( display.robotAddressBox, UserSettings.addresses, robotAddress); controlRequestFlags(); lastGroup = Group.groupForStream(robotAddress); Events.GGroupAdded.generate(this, lastGroup); } }); } }
private void setupFooter() { try { usedFileStore = Files.getFileStore(ToolSettings.NBITES_DIR_PATH); } catch (Exception e) { e.printStackTrace(); ; throw new Error(e); } Debug.warn("Tool footer using fileStore: %s", usedFileStore.name()); display.diskAvailLabel.setText(Utility.progressString(progressSize, 0.5)); display.jvmAvailLabel.setText(Utility.progressString(progressSize, 0.5)); footerJvmTimer = new Timer( 1000, // ms new ActionListener() { @Override public void actionPerformed(ActionEvent e) { footerJvmAction(); } }); footerJvmTimer.start(); footerDiskTimer = new Timer( 1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { footerDiskAction(); } }); footerDiskTimer.start(); }
public class JsonObject extends LinkedHashMap<JsonString, JsonValue> implements JsonValue { private static final DebugSettings debug = Debug.createSettings(true, true, true, Debug.INFO, null); @Override public JsonValueType type() { return JsonValueType.OBJECT; } public JsonValue put(String key, JsonValue value) { return this.put(new JsonString(key), value); } public JsonValue put(String key, String value) { return this.put(new JsonString(key), new JsonString(value)); } public JsonValue put(String key, int value) { return this.put(new JsonString(key), new JsonNumber(value)); } public JsonValue put(String key, boolean value) { return this.put(new JsonString(key), JsonBoolean.from(value)); } public JsonValue put(String key, long value) { // debug.info("{%s, %s}", key, new JsonNumber(value).toString()); return this.put(new JsonString(key), new JsonNumber(value)); } public JsonValue put(String key, double value) { return this.put(new JsonString(key), new JsonNumber(value)); } public JsonValue get(String key) { return super.get(new JsonString(key)); } public JsonValue remove(String key) { return super.remove(new JsonString(key)); } public boolean containsKey(String key) { return super.containsKey(new JsonString(key)); } @Override public JsonValue get(Object key) { if (key instanceof String) { return super.get(new JsonString((String) key)); } else if (key instanceof JsonString) { return super.get(key); } else { throw new IllegalArgumentException("JsonObject keys must be Strings or JsonStrings!"); } } @Override public String serialize() { Iterator<Entry<JsonString, JsonValue>> it = this.entrySet().iterator(); StringBuilder builder = new StringBuilder(); builder.append(JsonParser.TokenType.OBJECT_START.CHARACTER); while (it.hasNext()) { Entry<JsonString, JsonValue> entry = it.next(); debug.event("Entry: %s, %s", entry.getKey().toString(), entry.getValue().toString()); builder.append(entry.getKey().serialize()); builder.append(JsonParser.TokenType.OBJECT_DIVIDER.CHARACTER); builder.append(entry.getValue().serialize()); if (it.hasNext()) builder.append(JsonParser.TokenType.SEPARATOR.CHARACTER); } builder.append(JsonParser.TokenType.OBJECT_END.CHARACTER); return builder.toString(); } /* **************************** * this block defines the standard (only) way to implement these methods. * Because of Java syntax, there is no great way of moving these definitions * across classes. However, this section should be mirrored across Json classes */ @SuppressWarnings("unchecked") @Override public <T extends JsonValue> T cast() { return (T) this; } public JsonArray asArray() { return this.<JsonArray>cast(); } public JsonBoolean asBoolean() { return this.<JsonBoolean>cast(); } public JsonNumber asNumber() { return this.<JsonNumber>cast(); } public JsonObject asObject() { return this.<JsonObject>cast(); } public JsonString asString() { return this.<JsonString>cast(); } /* end mirrored section * ******************************/ @Override public String print() { return this.print(0); } @Override public String print(int indent) { Iterator<Entry<JsonString, JsonValue>> it = this.entrySet().iterator(); StringBuilder builder = new StringBuilder(); builder.append(Json.prefix(indent)); builder.append(JsonParser.TokenType.OBJECT_START.CHARACTER); builder.append("\n"); while (it.hasNext()) { Entry<JsonString, JsonValue> entry = it.next(); builder.append(Json.prefix(indent + 1)); builder.append(entry.getKey().serialize() + " "); builder.append(JsonParser.TokenType.OBJECT_DIVIDER.CHARACTER); builder.append("\n"); builder.append(entry.getValue().print(indent + 2)); if (it.hasNext()) builder.append(JsonParser.TokenType.SEPARATOR.CHARACTER); builder.append("\n"); } builder.append(Json.prefix(indent)); builder.append(JsonParser.TokenType.OBJECT_END.CHARACTER); return builder.toString(); } @Override public JsonValue copy() { JsonObject copy = new JsonObject(); for (Entry<JsonString, JsonValue> v : this.entrySet()) { copy.put(v.getKey().asString(), v.getValue().copy()); } return copy; } @Override public boolean congruent(JsonValue other) { if (other == null || other.type() != this.type()) { return false; } JsonObject obj = other.asObject(); if (obj.size() != this.size()) return false; for (Entry<JsonString, JsonValue> entry : this.entrySet()) { if (obj.containsKey(entry.getKey())) { if (!obj.get(entry.getKey()).congruent(entry.getValue())) return false; } else { return false; } } return true; } }
TitleListener() { Debug.event("TitleListener() listening..."); Center.listen(Events.CrossStatus.class, this, true); Center.listen(Events.RobotConnectionStatus.class, this, true); }
@Override public void valueForPathChanged(TreePath path, Object newValue) { Debug.error("logTree should not be editable..."); }
public class ToolDisplayHandler implements IOFirstResponder, Events.LogsFound, Events.LogRefsFound, Events.GroupAdded { private final long id = Utility.getNextIndex(this); private final ToolDisplayHandler outerThis = this; private static final Debug.DebugSettings debug = Debug.createSettings(Debug.INFO); @Override public String toString() { return this.getClass().getSimpleName() + "-" + id; } protected ToolDisplayHandler() { ToolMessage.displayInfo("creating new display and handler: %s", this); display = new ToolDisplay(); listener = new TitleListener(); setupUtilitiesTab(); setupControlTab(); setupLogsTab(); setupLogDisplay(); setupFooter(); Center.listen(Events.LogsFound.class, this, true); Center.listen(Events.LogRefsFound.class, this, true); Center.listen(Events.GroupAdded.class, this, true); final String boundsKey = this.toString(); Center.listen( new NBToolShutdownListener() { @Override public void nbtoolShutdownCallback() { DisplaySettings end = new DisplaySettings( display.getBounds(), viewProfile, display.topLevelSplit.getDividerLocation()); UserSettings.BOUNDS_MAP.put(boundsKey, end); } }); DisplaySettings ds = UserSettings.BOUNDS_MAP.get(boundsKey); if (ds != null) { display.setBounds(ds.bounds); display.topLevelSplit.setDividerLocation(ds.splitLocation); viewProfile = ds.profile == null ? ViewProfile.DEFAULT_PROFILE : ds.profile; } display.setTitle("nbtool v" + ToolSettings.VERSION + "." + ToolSettings.MINOR_VERSION); display.setMinimumSize(MIN_SIZE); if (id == 0) { display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } else { display.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); } setupKeyBindings(); display.topLevelSplit.setContinuousLayout(false); display.topLevelSplit.setAutoscrolls(false); Dimension min = ToolSettings.DEFAULT_BOUNDS.getSize(); min.width = 0; display.leftSideTabs.setMinimumSize(min); display.displayTabs.setMinimumSize(min); display.topLevelSplit.requestFocus(); } public void show(boolean vis) { display.setVisible(vis); } public boolean isVisible() { return display.isVisible(); } // ^^ EXTERNAL // ------------------------------------------ // vv INTERNAL private static final Dimension MIN_SIZE = new Dimension(800, 600); private final ToolDisplay display; private RobotConnection robot = null; private Group lastGroup = null; private ViewProfile viewProfile = ViewProfile.DEFAULT_PROFILE; private static <T> void updateComboBoxAndSettings(JComboBox<T> box, OrderedSet<T> set, T newest) { if (newest != null) set.update(newest); box.setModel(new DefaultComboBoxModel<T>(set.vector())); if (newest != null) box.setSelectedItem(newest); else if (set.vector().isEmpty()) { box.setSelectedIndex(-1); } else { box.setSelectedIndex(0); } } private void setupKeyBindings() { AbstractAction switchTabsAction = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { char key = e.getActionCommand().charAt(0); if (Character.isDigit(key)) { int n = (Character.getNumericValue(key) - 1); if (n >= 0 && n < display.displayTabs.getTabCount()) { display.displayTabs.setSelectedIndex(n); } return; } } }; AbstractAction loadAction = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { if (display.leftSideTabs.getSelectedComponent() == display.controlTab) display.loadButton.doClick(); } }; AbstractAction toggleLeftSideAction = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { if (display.topLevelSplit.getDividerLocation() > 10) { display.topLevelSplit.setDividerLocation(0); } else { display.topLevelSplit.setDividerLocation(0.5); display.topLevelSplit.requestFocus(); } } }; display.topLevelSplit.getActionMap().put("switchTabsAction", switchTabsAction); display.topLevelSplit.getActionMap().put("loadAction", loadAction); display.topLevelSplit.getActionMap().put("toggleLeftSideAction", toggleLeftSideAction); for (char c = '1'; c <= '9'; ++c) { display .topLevelSplit .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) .put(KeyStroke.getKeyStroke(c), "switchTabsAction"); } display .topLevelSplit .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) .put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "loadAction"); display .topLevelSplit .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) .put(KeyStroke.getKeyStroke('`'), "toggleLeftSideAction"); } private void setupViewProfileBox() { Collection<ViewProfile> set = ViewProfile.PROFILES.values(); display.viewProfileBox.setModel(new DefaultComboBoxModel<>(set.toArray(new ViewProfile[0]))); if (set.contains(viewProfile)) { display.viewProfileBox.setSelectedItem(viewProfile); } else { ViewProfile def = ViewProfile.DEFAULT_PROFILE; display.viewProfileBox.setSelectedItem(def); viewProfile = def; } } private void setupUtilitiesTab() { display.debugLevelBox.setModel( new DefaultComboBoxModel<Debug.LogLevel>(Debug.LogLevel.values())); display.debugLevelBox.setEditable(false); display.debugLevelBox.setSelectedIndex( Arrays.asList(Debug.LogLevel.values()).indexOf(Debug.level)); display.debugLevelBox.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int sel = display.debugLevelBox.getSelectedIndex(); Debug.level = Debug.LogLevel.values()[sel]; UserSettings.logLevel = Debug.level; Debug.print("changed Debug.level to: %s", Debug.level); } }); setupViewProfileBox(); display.viewProfileBox.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { ViewProfile prof = (ViewProfile) display.viewProfileBox.getSelectedItem(); if (prof != null) { viewProfile = prof; } } }); Center.listen( Events.ViewProfileSetChanged.class, new ViewProfileSetChanged() { @Override public void viewProfileSetChanged(Object src) { setupViewProfileBox(); } }, true); display.venueField.setText(UserSettings.venue); display.venueField.addKeyListener( new KeyAdapter() { @Override public void keyTyped(KeyEvent e) { UserSettings.venue = display.venueField.getText(); } }); JPanel utilityHolder = new JPanel(); // utilityHolder.setLayout(new BoxLayout(utilityHolder, // BoxLayout.Y_AXIS)); utilityHolder.setLayout(new GridLayout(0, 1)); for (UtilityParent up : UtilityManager.utilities) { utilityHolder.add(new UtilityPanel(up)); } // utilityHolder.add(Box.createVerticalGlue()); display.utilityScrollPane.setViewportView(utilityHolder); } private void controlSelectAction() { Path selected = PathChooser.chooseDirPath(display, null); if (selected != null) { if (FileIO.isValidLogFolder(selected)) { updateComboBoxAndSettings(display.pathBox, UserSettings.loadPathes, selected); } else { ToolMessage.displayError("invalid path to logs: %s", selected); } } } private void controlLoadAction() { if (robot == null) { Path selected = (Path) display.pathBox.getSelectedItem(); if (selected == null) { Debug.error("null path"); ToolMessage.display("load action: null path", Color.RED); return; } if (FileIO.isValidLogFolder(selected)) { updateComboBoxAndSettings(display.pathBox, UserSettings.loadPathes, selected); lastGroup = Group.groupFromPath(selected); LogReference[] added; try { added = FileIO.readAllRefsFromPath(selected, true); } catch (Throwable e) { ToolMessage.displayError( "error {%s} (see below) reading Log refs from %s", e.getMessage(), selected); e.printStackTrace(); return; } lastGroup.add(added); // Log[] addedLogs = new Log[added.length]; // for (int i = 0; i < added.length; ++i) // addedLogs[i] = added[i].get(); ToolMessage.displayInfo("loaded %d logs into %s", added.length, lastGroup); Events.GGroupAdded.generate(this, lastGroup); Events.GLogRefsFound.generate(this, added); // Events.GLogsFound.generate(this, addedLogs); display.leftSideTabs.setSelectedComponent(display.logTab); } else { Debug.error("invalid Log folder: " + selected.toString()); ToolMessage.display("invalid Log folder: " + selected.toString(), Color.RED); return; } } else { Debug.error("cannot load session while streaming (%s)", robot); ToolMessage.display("cannot load session while streaming", Color.ORANGE); } } private void controlRequestFlags() { LogRPC.requestFlags( new IOFirstResponder() { @Override public void ioFinished(IOInstance instance) { assert (false); } @Override public void ioReceived(IOInstance inst, int ret, Log... out) { if (inst != robot) { Debug.error( "got requestFlags return from instance %s, expected from %s!", inst, robot); } else { assert (out.length == 1); Log flags = out[0]; assert (flags.logClass.equals(SharedConstants.LogClass_Flags())); RobotFlag[] parsedFlags = RobotFlag.parseLog(flags); JPanel container = new JPanel(); container.setLayout(new GridLayout(parsedFlags.length, 1)); for (RobotFlag val : parsedFlags) { container.add(new FlagPanel(robot, val)); } container.setMinimumSize(container.getPreferredSize()); display.rpcScrollPane.setViewportView(container); } } @Override public boolean ioMayRespondOnCenterThread(IOInstance inst) { return false; } }, robot); } private class ControlConnectRunnable extends Center.EventRunnable { private final String robotAddress; ControlConnectRunnable(String s) { this.robotAddress = s; } @Override protected void run() { Debug.warn("trying to connect to %s", robotAddress); robot = RobotConnection.connectToRobot(robotAddress, outerThis); if (robot == null) { ToolMessage.displayError("connection failed to: %s", robotAddress); SwingUtilities.invokeLater( new Runnable() { @Override public void run() { display.connectButton.setEnabled(true); } }); return; } else { ToolMessage.displayWarn("SUCCESS: connected to %s (%s)", robotAddress, robot); SwingUtilities.invokeLater( new Runnable() { @Override public void run() { display.connectButton.setEnabled(true); display.connectButton.setText("disconnect"); display.loadButton.setEnabled(false); updateComboBoxAndSettings( display.robotAddressBox, UserSettings.addresses, robotAddress); controlRequestFlags(); lastGroup = Group.groupForStream(robotAddress); Events.GGroupAdded.generate(this, lastGroup); } }); } } } private void controlConnectAction() { if (robot == null) { assert (display.connectButton.getText().equals("connect")); } else { assert (display.connectButton.getText().equals("disconnect")); Debug.info("trying to kill %s", robot); final RobotConnection _robot = robot; Center.addEvent( new Center.EventRunnable() { @Override protected void run() { _robot.kill(); } }); return; } String address = (String) display.robotAddressBox.getSelectedItem(); if (address == null) { ToolMessage.displayError("choose valid address"); return; } address = address.trim(); if (display.localCheckBox.isSelected() && !address.endsWith(".local")) { address += ".local"; } display.connectButton.setEnabled(false); Center.addEvent(new ControlConnectRunnable(address)); } private void setupKeepSlider() { Hashtable<Integer, JLabel> labelTable = new Hashtable<>(); labelTable.put(new Integer(0), new JLabel("0.0")); labelTable.put(new Integer(1), new JLabel("0.01")); labelTable.put(new Integer(2), new JLabel("0.1")); labelTable.put(new Integer(3), new JLabel("0.2")); labelTable.put(new Integer(4), new JLabel("1.0")); display.keepSlider.setSnapToTicks(true); display.keepSlider.setMinimum(0); display.keepSlider.setMaximum(labelTable.size() - 1); display.keepSlider.setLabelTable(labelTable); display.keepSlider.setPaintLabels(true); display.keepSlider.setPaintTicks(true); display.keepSlider.setValue(labelTable.size() - 1); } private int keepMod() { int val = display.keepSlider.getValue(); switch (val) { case 0: return 0; case 1: return 100; case 2: return 10; case 3: return 5; case 4: return 1; default: debug.error("bad keepSlider value: %d", val); return -1; } } private boolean shouldKeep(long index) { int km = keepMod(); return (km > 0) && ((index % km) == 0); } @SuppressWarnings("unchecked") private void setupControlTab() { updateComboBoxAndSettings(display.pathBox, UserSettings.loadPathes, null); updateComboBoxAndSettings(display.robotAddressBox, UserSettings.addresses, null); final String last = "don't stream"; Vector<String> streamVector = new Vector<String>(); for (Pair<String, Criteria> pair : LogSearching.CRITERIA) { streamVector.add("stream: " + pair.a); } streamVector.add(last); display.streamComboBox.setModel(new DefaultComboBoxModel<String>(streamVector)); display.streamComboBox.setSelectedItem(last); display.selectButton.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { controlSelectAction(); } }); display.loadButton.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { controlLoadAction(); } }); display.connectButton.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { controlConnectAction(); } }); setupKeepSlider(); // Stop streaming if the user selects a log... Center.listen( Events.LogSelected.class, new Events.LogSelected() { @Override public void logSelected(Object source, Log first, List<Log> alsoSelected) { debug.info("Log{%s} selected, %s disabling streaming!", first, outerClassThis); display.streamComboBox.setSelectedItem(last); } }, true); display.leftSideTabs.setSelectedComponent(display.controlTab); ; } private ArrayList<LogReference> currentlyDisplayedFrom(Group group) { ArrayList<LogReference> refs = new ArrayList<>((group).logs); LogSearching.Criteria criteria = LogSearching.criteriaAt(display.sasStreamProfile.getSelectedIndex()); if (criteria != null) { for (int i = 0; i < refs.size(); ) { if (!criteria.fits(refs.get(i).description)) refs.remove(i); else ++i; } } LogSorting.Sort sort = (LogSorting.Sort) display.sasOrderBox.getSelectedItem(); if (sort != null) { Collections.sort(refs, sort.comparator); } return refs; } private boolean resemblesGeneratedFilename(String name, LogReference ref) { String[] checks = new String[] { String.format("%s_%s_v%d", ref.host_name, ref.logClass, ToolSettings.VERSION), String.format("temp_log_id"), String.format("log_%s_", ref.logClass) }; for (String check : checks) { if (name.startsWith(check)) return true; } return false; } private class LogTreeModel implements TreeModel, TreeSelectionListener, LogDNDSource, TreeCellRenderer { private final DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); @Override public Component getTreeCellRendererComponent( JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { JLabel rendered = (JLabel) renderer.getTreeCellRendererComponent( tree, value, selected, expanded, leaf, row, hasFocus); if (value instanceof Group) { Group group = (Group) value; rendered.setText(group.guiString()); } else if (value instanceof LogReference) { LogReference reference = (LogReference) value; if (!reference.temporary()) { // rendered.setText(reference.loadPath().getFileName().toString()); // rendered.setText("" + reference.loadPath().getFileName().toString().length()); Path lp = reference.loadPath(); String last = lp.getFileName().toString(); if (last.length() < 20 || !resemblesGeneratedFilename(last, reference)) { rendered.setText(last); } else { rendered.setText(reference.guiString()); } } else { rendered.setText(reference.guiString()); } } return rendered; } @Override public void valueChanged(TreeSelectionEvent e) { if (!e.isAddedPath()) { // path unselected, ignore return; } TreePath[] selected = display.logTree.getSelectionPaths(); switch (selected[0].getPathCount()) { case 0: Debug.error("null selection!"); break; case 1: Debug.error("root selected!"); break; case 2: { Group group = (Group) selected[0].getLastPathComponent(); displayGroup(group); Events.GGroupSelected.generate(this, group); } return; case 3: { List<Log> all = new LinkedList<>(); for (TreePath path : selected) { if (path.getPathCount() != 3) continue; // it isn't a Log selection LogReference ref = (LogReference) path.getLastPathComponent(); all.add(ref.get()); } Log first = all.remove(0); displayLog(first, all); Events.GLogSelected.generate(outerClassThis, first, all); } return; default: Debug.error( "selection count %d %s", selected[0].getPathCount(), selected[0].getLastPathComponent()); } } @Override public Object getRoot() { return this; } @Override public Object getChild(Object parent, int index) { if (parent == this) { return AllGroups.get(index); } else if (parent instanceof Group) { Group group = (Group) parent; return currentlyDisplayedFrom(group).get(index); } else return null; } @Override public int getChildCount(Object parent) { if (parent == this) { return AllGroups.getGroupCount(); } else if (parent instanceof Group) { return currentlyDisplayedFrom((Group) parent).size(); } else { return 0; } } @Override public boolean isLeaf(Object node) { return node.getClass() == LogReference.class; } @Override public void valueForPathChanged(TreePath path, Object newValue) { Debug.error("logTree should not be editable..."); } @Override public int getIndexOfChild(Object parent, Object child) { if (parent == this) { return AllGroups.allGroups.indexOf(child); } else if (parent instanceof Group) { return currentlyDisplayedFrom((Group) parent).indexOf(child); } else { Debug.error("parent %s not container!", parent); return -1; } } private final ArrayList<TreeModelListener> listeners = new ArrayList<TreeModelListener>(); @Override public void addTreeModelListener(TreeModelListener l) { listeners.add(l); } @Override public void removeTreeModelListener(TreeModelListener l) { listeners.remove(l); } @Override public Log[] supplyLogsForDrag() { ArrayList<Log> refs = new ArrayList<>(); for (TreePath tp : display.logTree.getSelectionPaths()) { if (tp.getPathCount() == 3) { LogReference reference = (LogReference) tp.getLastPathComponent(); refs.add(reference.get()); } } return refs.toArray(new Log[0]); } protected void deleteCurrent() { int num_logs_deleted = 0; Set<Group> groups_changed = new HashSet<>(); for (TreePath tp : display.logTree.getSelectionPaths()) { if (tp.getPathCount() == 3) { Group group = (Group) tp.getPath()[1]; LogReference reference = (LogReference) tp.getLastPathComponent(); Debug.warn("deleting {%s} from {%s}", reference, group); group.remove(reference); ++num_logs_deleted; groups_changed.add(group); } else { Debug.warn("cannot delete {%s}", tp.getLastPathComponent()); } } for (Group group : groups_changed) { TreeModelEvent removeEvent = new TreeModelEvent(this, new Object[] {this, group}); for (TreeModelListener listener : listeners) listener.treeStructureChanged(removeEvent); } ToolMessage.displayAndPrint("deleted %d logs", num_logs_deleted); } protected void showGroupAdded(Group group) { // TreeModelEvent tme = new TreeModelEvent(this, new Object[]{root}, // new int[]{AllGroups.allGroups.indexOf(group)}, // new Object[]{group}); Debug.event("LogModel group added"); TreeModelEvent changed = new TreeModelEvent(this, new Object[] {this}); for (TreeModelListener listener : listeners) listener.treeStructureChanged(changed); } protected void showReferenceAdded(LogReference reference) { Debug.event("LogModel reference added"); TreeModelEvent tme = new TreeModelEvent(this, new Object[] {this, reference.container}); for (TreeModelListener l : listeners) { l.treeStructureChanged(tme); } } protected void treeReSorted() { Debug.event("LogModel tree resorted"); TreeModelEvent tme = new TreeModelEvent(this, new Object[] {this}); for (TreeModelListener l : listeners) { l.treeStructureChanged(tme); } } } private LogTreeModel model; private final ToolDisplayHandler outerClassThis = this; private void setupLogsTab() { String last = "don't filter"; Vector<String> streamVector = new Vector<String>(); for (Pair<String, Criteria> pair : LogSearching.CRITERIA) { streamVector.add("search for: " + pair.a); } streamVector.add(last); ActionListener tellModel = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { model.treeReSorted(); } }; display.sasStreamProfile.setModel(new DefaultComboBoxModel<String>(streamVector)); display.sasStreamProfile.setSelectedItem(last); display.sasStreamProfile.addActionListener(tellModel); display.sasOrderBox.setModel(new DefaultComboBoxModel<>(LogSorting.Sort.values())); display.sasOrderBox.setSelectedItem(LogSorting.Sort.BY_ARRIVAL); display.sasOrderBox.addActionListener(tellModel); model = new LogTreeModel(); display.logTree.setModel(model); display.logTree.setCellRenderer(model); display.logTree.setEditable(false); display.logTree.setRootVisible(false); display.logTree.setScrollsOnExpand(true); display .logTree .getSelectionModel() .setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); display.logTree.addTreeSelectionListener(model); LogDND.makeComponentSource(display.logTree, model); display.logTree.addKeyListener( new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_DELETE || e.getKeyCode() == KeyEvent.VK_BACK_SPACE) { model.deleteCurrent(); } } }); } private void displayLog(Log log) { displayLog(log, new LinkedList<Log>()); } private void displayLog(Log log, List<Log> also) { tabDisplayer.setContents(viewProfile, log, also); } private void displayGroup(Group g) { tabDisplayer.setContents(g); } private ToolDisplayTabs tabDisplayer = null; private void setupLogDisplay() { LogDND.makeComponentTarget( display.displayTabs, new LogDNDTarget() { @Override public void takeLogsFromDrop(Log[] log) { if (log.length < 1) return; List<Log> list = new LinkedList<>(Arrays.asList(log)); displayLog(list.remove(0), list); } }); tabDisplayer = new ToolDisplayTabs(display); } TitleListener listener = null; class TitleListener implements Events.CrossStatus, Events.RobotConnectionStatus { TitleListener() { Debug.event("TitleListener() listening..."); Center.listen(Events.CrossStatus.class, this, true); Center.listen(Events.RobotConnectionStatus.class, this, true); } int numCross = 0; int numRobot = 0; @Override public void robotStatus(RobotConnection inst, boolean up) { numRobot += up ? 1 : -1; set(); } @Override public void nbCrossFound(CrossInstance inst, boolean up) { numCross += up ? 1 : -1; set(); } private void set() { display.setTitle( String.format("nbtool - %d CrossInstance, %d RobotConnection", numCross, numRobot)); } } private Timer footerJvmTimer = null; private Timer footerDiskTimer = null; private final int progressSize = 50; private FileStore usedFileStore = null; private void setupFooter() { try { usedFileStore = Files.getFileStore(ToolSettings.NBITES_DIR_PATH); } catch (Exception e) { e.printStackTrace(); ; throw new Error(e); } Debug.warn("Tool footer using fileStore: %s", usedFileStore.name()); display.diskAvailLabel.setText(Utility.progressString(progressSize, 0.5)); display.jvmAvailLabel.setText(Utility.progressString(progressSize, 0.5)); footerJvmTimer = new Timer( 1000, // ms new ActionListener() { @Override public void actionPerformed(ActionEvent e) { footerJvmAction(); } }); footerJvmTimer.start(); footerDiskTimer = new Timer( 1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { footerDiskAction(); } }); footerDiskTimer.start(); } private void footerJvmAction() { long jvmUsed = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed(); long jvmMax = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax(); double jvmFrac = ((double) jvmUsed) / ((double) jvmMax); display.jvmAvailLabel.setText(Utility.progressString(progressSize, jvmFrac)); // display.footerExtraLabel.setText( String.format( " %d logs, %sused, %smax", AllGroups.getLogCount(), Utility.byteString(jvmUsed, true, true, false, false), Utility.byteString(jvmMax, true, true, false, false))); // Debug.print("jvm %d %s", jvmFrac, // String.format("%d logs, %s used memory, %s max", // AllGroups.getLogCount(), Utility.byteString(jvmUsed, true, true, // false, false), // Utility.byteString(jvmMax, true, true, false, false)) // ); } private void footerDiskAction() { long diskSpace; long diskUsed; try { diskSpace = usedFileStore.getTotalSpace(); diskUsed = diskSpace - usedFileStore.getUnallocatedSpace(); } catch (IOException e) { e.printStackTrace(); throw new Error(e); } double diskFrac = ((double) diskUsed) / ((double) diskSpace); display.diskAvailLabel.setText(Utility.progressString(progressSize, diskFrac)); } /* * Events interface implementations... */ @Override public void groupAdded(Object source, Group group) { model.showGroupAdded(group); } @Override public void logsFound(Object source, Log... found) { for (Log log : found) { LogReference ref = log.getReference(); if (ref != null) { model.showReferenceAdded(ref); } } } @Override public void logRefsFound(Object source, LogReference... found) { for (LogReference ref : found) { model.showReferenceAdded(ref); } } /* * IO implementation... */ @Override public void ioFinished(IOInstance instance) { if (instance == robot) { ToolMessage.displayWarn("robot %s disconnected!", instance); display.rpcScrollPane.setViewportView(new JLabel("no connection")); display.connectButton.setText("connect"); display.loadButton.setEnabled(true); robot = null; } else { Debug.error("informed of dead connection %s but robot=%s", instance, robot); } } @Override public void ioReceived(IOInstance inst, int ret, Log... out) { if (inst == robot) { // Deal with streaming... LogSearching.Criteria criteria = LogSearching.criteriaAt(display.streamComboBox.getSelectedIndex()); if (criteria != null) { Log pass = null; for (Log l : out) { if (criteria.fits(l.getFullDescription())) pass = l; } if (pass != null) displayLog(pass); } // Deal with adding to groups (i.e. keeping)... assert (lastGroup != null); for (Log l : out) { if (shouldKeep(l.jvm_unique_id)) lastGroup.add(LogReference.referenceFromLog(l)); } Events.GLogsFound.generate(this, out); } else { Debug.error("%s got %d surprising logs from %s", this, out.length, inst); } } @Override public boolean ioMayRespondOnCenterThread(IOInstance inst) { return false; } }