/** * Copyright (c) 2014 Matthias Jaenicke <matthias.jaenicke@student.kit.edu>, * Matthias Plappert <undkc@student.kit.edu>, * Julien Duman <uncyc@student.kit.edu>, * Christian Dreher <uaeef@student.kit.edu>, * Wasilij Beskorovajnov <uajkm@student.kit.edu> and * Aydin Tekin <aydin.tekin@student.kit.edu> * * Released under the MIT license (refer to LICENSE.md) * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package edu.kit.iks.CryptographicsLib; import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JLabel; import javax.swing.JPanel; /** * * @author Matthias Jaenicke * * A bar diagram to show the frequencies of characters in a given text in comparison. * * This bar diagram has a vertical beam for each character, with the beam for the most used character being at * maximum height of the diagram. Each other beam has a corresponding fraction of this height. * The equivalent characters are displayed beneath each beam. * The number of occurrences of each character is displayed within or above each beam, * depending on the height of the beam. */ public class CharacterFrequencyDiagramView extends JPanel { /** * Serial version UID */ private static final long serialVersionUID = -9014431293164765696L; // Quantities of all characters private int [] occurrences; private String histogramText; /** * Generates a diagram showing character frequencies with the given parameters. * @param text Text which is analyzed and has its character occurrences displayed. * Non-alphabetical characters are simply ignored. * @param width Total width of the diagram. Each column and the gaps between them will be a fraction of it. * Has to be at least 405 to work properly. * @param height Total height of the diagram. Has to be at least 60 to work properly. */ public CharacterFrequencyDiagramView(String text, int width, int height) { super(); this.histogramText = text; this.occurrences = calculateOccurrences(text); int padding = (int)(width / occurrences.length * 0.10); GridLayout layout = new GridLayout(1, occurrences.length, 0, padding); this.setLayout(layout); generateDiagram(width, height); this.setPreferredSize(new Dimension(width, height)); this.setVisible(true); } private void generateDiagram(int totalWidth, int totalHeight) { // Determine the width of a single beam with regard of gaps between beams. int singleWidth = (int)(totalWidth * 0.9 / occurrences.length); // Determine the base value for calculating the height of each column. int maxOccurrences = 0; for (int occ: occurrences) { if (occ > maxOccurrences) { maxOccurrences = occ; } } // "- 20" for putting the corresponding character beneath each beam. float heightBase = (float)(totalHeight - 20) / maxOccurrences; int asciiA = 65; for (int i = 0; i < occurrences.length; i++) { // Calculate the rounded height for the beam int height = (int)(heightBase * occurrences[i] + 0.5); JPanel beam = generateBeam((char)(i+asciiA), occurrences[i], singleWidth, height); this.add(beam); } } // Generates an entire beam including its value and corresponding character. private JPanel generateBeam(char character, int occurrence, int width, int height) { JPanel beam = new JPanel(); BoxLayout layout = new BoxLayout(beam, BoxLayout.Y_AXIS); beam.setLayout(layout); // A filler to get the beam to the bottom of the panel. beam.add(Box.createVerticalGlue()); JLabel coloredBeam; // If the beam is too short, the number of occurrences will be displayed above it. if (height < 20) { // Label to display number of occurrences. JLabel number = new JLabel("" + occurrence); number.setName("histogramFont"); number.setMinimumSize(new Dimension(width, 20)); number.setPreferredSize(new Dimension(width, 20)); number.setMaximumSize(new Dimension(width, 20)); number.setHorizontalAlignment(JLabel.CENTER); beam.add(number); // An empty label for the actual beam coloredBeam = new JLabel(); } else { // A label for the actual beam. Contains the number of occurrences of its character. coloredBeam = new JLabel("" + occurrence); coloredBeam.setName("histogramFont"); coloredBeam.setVerticalAlignment(JLabel.TOP); coloredBeam.setHorizontalAlignment(JLabel.CENTER); coloredBeam.setForeground(Color.white); } coloredBeam.setOpaque(true); coloredBeam.setBackground(Color.BLUE.darker()); coloredBeam.setMinimumSize(new Dimension(width, height)); coloredBeam.setPreferredSize(new Dimension(width, height)); coloredBeam.setMaximumSize(new Dimension(width, height)); beam.add(coloredBeam); // The "legend" of the beam, i.a. its corresponding character. JLabel text = new JLabel("" + character); text.setMinimumSize(new Dimension(width, 20)); text.setPreferredSize(new Dimension(width, 20)); text.setMaximumSize(new Dimension(width, 20)); text.setHorizontalAlignment(JLabel.CENTER); beam.add(text); return beam; } // Calculates the number of occurrences of alphabetical characters in the given String. // All other characters are ignored. // Returns an Integer array with 26 items, each representing the "index+1"th character of the alphabet // and containing its number of occurrences. private int[] calculateOccurrences(String text) { int[] result = new int[26]; text = text.toUpperCase(); for(int i = 0; i < result.length; i++) { result[i] = 0; } int asciiA = 65; boolean inHtmlTag = false; for(int i = 0; i < text.length(); i++) { char c = text.charAt(i); int index = (int)c - asciiA; if (c == '<' || c == '>') { inHtmlTag = !inHtmlTag; } else if (!inHtmlTag && index >= 0 && index < result.length) { result[index]++; } } return result; } public int[] getOccurences() { return occurrences; } public void setOccurrences(int [] occurrences) { this.occurrences = occurrences; } /** * @return the histogramText */ public String getHistogramText() { return histogramText; } }