/******************************************************************************* * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. * * 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 hr.fer.zemris.vhdllab.applets.simulations; import java.awt.Dimension; import java.awt.Graphics; import java.util.ArrayList; import java.util.List; import javax.swing.JPanel; import javax.swing.JScrollBar; /** * Panel koji sadrzi imena signala * * @author Boris Ozegovic */ class SignalNamesPanel extends JPanel { /** Prvo ime signala pocinje od 30-tog piksela */ private static final int YAXIS_START_POINT = 30; /** Svako se ime nalazi u springu (elasticnom pretincu) koji je visine 45 piksela */ private static final int SIGNAL_NAME_SPRING_HEIGHT = 45; /** Maksimalna duljina koju panel moze poprimiti iznosi 650 piksela */ private static final int PANEL_MAX_WIDTH = 650; /** Lista Stringova koje sadrzi sva imena signala */ private List<String> signalNames; /** Sadrzi rezultate simulacije */ private GhdlResults results; /** Polozaj trenutnog springa */ private int yAxis; /** Trenutni offset po Y-osi */ private int offsetYAxis; /** Trenutni offset po X-osi */ private int offsetXAxis; /** Makimalna duljina imena signala */ private int maximumSignalNameLength; /** Sirina panela s imenima signala */ private int panelWidth; /** * Ako je kliknut border izmedu panela imena i valnih oblika tada je moguce rastegnuti * panel s imenima signala (ako je kliknut i ako se povuce, panel se rasteze) */ private boolean isBorderClicked = false; /** Sadrzi informaciju jesu li bit-vectori prosireni */ private List<Boolean> expandedSignalNames = new ArrayList<Boolean>(); /** * Lista trenutnih indeksa vektora u listi sa signalima */ private List<Integer> currentVectorIndex = new ArrayList<Integer>(); /** Varijabla koja sadrzi informaciju je li trenutni signal oznacen misem */ private boolean isClicked = false; /** Sadrzi indeks trenutno oznacenog signala misem */ private int index = -1; /** ScrollBar */ private JScrollBar scrollbar; /** Boje */ private ThemeColor themeColor; /** SerialVersionUID */ private static final long serialVersionUID = 1; /** * Constructor * * @param themeColor trenutna tema */ public SignalNamesPanel (ThemeColor themeColor, JScrollBar scrollbar) { super(); this.scrollbar = scrollbar; this.themeColor = themeColor; } /** * Metoda postavlja novo stanje panela s imenima signala u ovisnosti o * rezultatu kojeg vraca GhdlResult * * @param results rezultati koje parsira GhdlResult */ public void setContent(GhdlResults results) { this.results = results; this.signalNames = results.getSignalNames(); this.expandedSignalNames = results.getExpandedSignalNames(); this.currentVectorIndex = results.getCurrentVectorIndex(); this.maximumSignalNameLength = results.getMaximumSignalNameLength(); this.panelWidth = this.maximumSignalNameLength * 6; } /** * Getter koji vraca preferirane dimenzije */ @Override public Dimension getPreferredSize() { return new Dimension(panelWidth + 4, signalNames.size() * SIGNAL_NAME_SPRING_HEIGHT); } /** * Getter koji vraca preferirane dimenzije ako je ime najvece duljine manje * od 650 piksela, inace vraca 650 piksela */ @Override public Dimension getMaximumSize() { if (panelWidth < PANEL_MAX_WIDTH) { return new Dimension(panelWidth, signalNames.size() * SIGNAL_NAME_SPRING_HEIGHT); } return new Dimension(PANEL_MAX_WIDTH, signalNames.size() * SIGNAL_NAME_SPRING_HEIGHT); } /** * Postavlja novu vrijednosti maksimalne velicine imena signala * * @param panelWidth nova vrijednost */ public void setPanelWidth (int panelWidth) { this.panelWidth = panelWidth; } /** * Vraca sirinu panela */ public int getPanelWidth () { return panelWidth; } /** * Setter koji postavlja vertikalni offset * * @param offset Zeljeni novi offset */ public void setVerticalOffset (int offset) { this.offsetYAxis = offset; } /** * Vraca trenutni vertikalni offset */ public int getVerticalOffset () { return offsetYAxis; } /** * Setter koji postavlja horizontalni offset * *@param offset Zeljeni novi offset */ public void setHorizontalOffset (int offset) { this.offsetXAxis = offset; } /** * Metoda postavlja novi set imena signala * * @param signalNames Nove set imena signala */ public void setSignalNames (List<String> signalNames) { this.signalNames = signalNames; } /** * Postavlja informaciju treba li oznaciti signal * * @param isClicked true or false */ public void setIsClicked (boolean isClicked) { this.isClicked = isClicked; } /** * Postavlja trenutni indeks oznacenog signala * * @param index indeks oznacenog signala */ public void setIndex (int index) { this.index = index; } /** * Vraca informaciju je li signal oznacen * * @return true ako je kliknut, inace false */ public boolean getIsClicked () { return isClicked; } /** * Vraca indeks trenutno oznacenog signala * * @return Index kliknutog signala, inace vraca -1 */ public int getIndex () { return index; } /** * Vraca visinu springa u kojoj je smjesteno ime signala */ public int getSignalNameSpringHeight () { return SIGNAL_NAME_SPRING_HEIGHT; } /** * Ako je border izmedu imena signala i valnih oblika kliknut * * @param isBorderClicked Je ili nije */ public void setIsBorderClicked (boolean isBorderClicked) { this.isBorderClicked = isBorderClicked; } /** * Vrati trenutnu informaciju je li border kliknut ili nije */ public boolean getIsBorderClicked () { return isBorderClicked; } /** * Vraca visinu panela u pikselima */ public int getPanelHeightInPixels() { return signalNames.size() * SIGNAL_NAME_SPRING_HEIGHT; } /** * Vraca velicinu panela trenutno vidljivog na ekranu */ public int getPanelHeight () { return getHeight(); } /** * Helper function for vector limits extraction. * @param name full name of vector, eg. "+ /tb_d[0:15]" * @return an 2-element array containing limits, eg. [0,15] */ private static int[] extractVectorLimits(String name) { int start = name.indexOf('['); int end = name.indexOf(']'); int colon = name.indexOf(':'); return new int[] { Integer.parseInt(name.substring(start+1, colon)), Integer.parseInt(name.substring(colon+1, end)) }; } /** * Ekspandira bit-vektor. Umjesto bit-vektora zapisuju se njegovi clanovi u listu signala. * Npr. Umjesto A[0:2] ulaze A[0], A[1] i A[2] * * @param index Index bit-vektora koji se ekspandira */ public void expand (int index) { /* defaultIndex je index bit-vektora u default polju imena signala s kojim se barata */ Integer defaultIndex = currentVectorIndex.get(index); String tempSignalName; int[] limits = extractVectorLimits(signalNames.get(index)); int startVector = limits[0]; int endVector = limits[1]; /* GRANICE MOGU BITI I VISEZNAMENKASTI BROJEVI!!! * int startVector = Integer.valueOf(signalNames.get(index) .charAt(signalNames.get(index).length() - 4)) - 48; int endVector = Integer.valueOf(signalNames.get(index) .charAt(signalNames.get(index).length() - 2)) - 48; */ /* duljine vektora, s tim da je duljina umanjena za 1 od stvarne duljine */ int vectorSize = Math.abs(startVector - endVector); /* Izvadi ime vektora bez oznake velicine vektora ([...]) */ tempSignalName = signalNames.get(index).substring(1, signalNames.get(index).indexOf('[')); // tempSignalName = signalNames.get(index).substring(1, // signalNames.get(index).length() - 5); signalNames.remove(index); signalNames.add(index, "-" + tempSignalName + "[" + startVector + "]"); if (startVector < endVector) { startVector++; } else { startVector--; } for (int j = 0; j < vectorSize; j++) { signalNames.add(index + 1 + j, " " + tempSignalName + "[" + startVector + "]"); if (startVector < endVector) { startVector++; } else { startVector--; } //(startVector < endVector) ? (startVector++) : (startVector--); } /* * refresha currentVectorIndex listu */ for (int i = 0; i < vectorSize; i++) { currentVectorIndex.add(index, defaultIndex); } } /** * Kolapsira bit-vektor nakon sto se klikne minus ispred imena signala * * @param index Index bit-vektora koji se kolapsira */ public void collapse (int index) { Integer defaultIndex = currentVectorIndex.get(index); int vectorSize = results.getDefaultSignalValues()[defaultIndex][0].length(); for (int i = 0; i < vectorSize; i++) { signalNames.remove(index); } signalNames.add(index, results.getDefaultSignalNames()[defaultIndex]); /* Refresha currentVectorIndex listu nakon kolapsiranja odredenog bit-vektora */ for (int i = 0; i < vectorSize - 1; i++) { currentVectorIndex.remove(index); } } /** * Crta komponentu * * @param g Graphics objekt */ @Override public void paintComponent (Graphics g) { super.paintComponent(g); /* postavi vrijednost scrollbara */ scrollbar.setMaximum(this.getMaximumSize().width); setBackground(themeColor.getSignalNames()); /* ako treba oznaciti neki od signala */ if (isClicked) { g.setColor(themeColor.getApplet()); g.fillRect(0, index * SIGNAL_NAME_SPRING_HEIGHT + 15 - offsetYAxis, getMaximumSize().width, SIGNAL_NAME_SPRING_HEIGHT / 2 + 5); } g.setColor(themeColor.getLetters()); yAxis = YAXIS_START_POINT - offsetYAxis; for (int i = 0; i < signalNames.size(); i++) { if (i < currentVectorIndex.size() && currentVectorIndex.get(i) != -1) { Integer defaultIndex = currentVectorIndex.get(i); if (expandedSignalNames.get(defaultIndex)) { int vectorSize = results.getDefaultSignalValues() [defaultIndex][0].length(); g.drawString(signalNames.get(i), 5 - offsetXAxis, yAxis); g.drawLine(7 - offsetXAxis, yAxis, 7 - offsetXAxis, yAxis + 10); yAxis += SIGNAL_NAME_SPRING_HEIGHT; for (int j = 0; j < vectorSize - 1; j++) { g.drawString(signalNames.get(++i), 5 - offsetXAxis, yAxis); g.drawLine(7 - offsetXAxis, yAxis - 2, 7 - offsetXAxis, yAxis - SIGNAL_NAME_SPRING_HEIGHT); g.drawLine(7 - offsetXAxis, yAxis - 2, 9 - offsetXAxis, yAxis - 2); yAxis += SIGNAL_NAME_SPRING_HEIGHT; } } else { g.drawString(signalNames.get(i), 5 - offsetXAxis, yAxis); yAxis += SIGNAL_NAME_SPRING_HEIGHT; } } else { g.drawString(signalNames.get(i), 5 - offsetXAxis, yAxis); yAxis += SIGNAL_NAME_SPRING_HEIGHT; } } } }