// Copyright 1996, David Neto import java.awt.*; import java.lang.*; // needed for sleep public class MergeSortActivation extends Panel { static int MSAInstanceNumber = 0; MergeSortApp msa; Ticker ticker; Sorter sorter; ComparisonLabel CCLabel; int rewindMaxVal, rewindIntValues[], rewindLo, rewindHi; int myInstanceNumber; GridBagLayout gridBag; GridBagConstraints c; Insets theseInsets; boolean isActive; boolean showBound, showCount; MergeSortActivation left, right, parent; int offset; // number of parent elements preceding the first element in this activation BarPanel bp; int len; int maxVal; int comparisonCount, comparisonUpperBound; int thisLo, thisHi; public MergeSortActivation( MergeSortApp msa, Ticker ticker, MergeSortActivation parent, int parentLo, int maxVal, int values[], int lo, int hi, boolean showBound, boolean showCount) { myInstanceNumber = MSAInstanceNumber++; this.msa = msa; this.ticker = ticker; theseInsets = new Insets(2,6,0,0); setLayout(new GridLayout(1,0)); this.parent = parent; this.offset = lo-parentLo; this.showBound = showBound; this.showCount = showCount; this.maxVal = maxVal; this.len = hi-lo; thisLo = lo; thisHi = hi; if ( hi-lo > 1 ) { int mid = (lo + hi) / 2; left = new MergeSortActivation(msa,ticker,this,lo,maxVal,values,lo,mid,showBound,showCount); right = new MergeSortActivation(msa,ticker,this,lo,maxVal,values,mid,hi,showBound,showCount); comparisonUpperBound = left.getComparisonUpperBound() + right.getComparisonUpperBound() + hi-lo; /* This can be hi-lo-1, but I don't think there is a symbol for <= */ } else { left = right = null; comparisonUpperBound = 0; } bp = new BarPanel(maxVal,values,lo,hi); // Add the panels to the Container gridBag = new GridBagLayout(); setLayout(gridBag); c = new GridBagConstraints(); c.weighty = -1.0; c.gridwidth = GridBagConstraints.REMAINDER; c.fill = GridBagConstraints.HORIZONTAL; c.anchor = GridBagConstraints.NORTH; // Button UBButton = new Button("Upper bound"); // gridBag.setConstraints(UBButton,c); // add(UBButton); CCLabel = new ComparisonLabel(comparisonUpperBound); if ( comparisonUpperBound > 0 ) { // Only add CCLabel if > 0. gridBag.setConstraints(CCLabel,c); add(CCLabel); } c.fill = GridBagConstraints.NONE; gridBag.setConstraints(bp,c); add(bp); if ( hi-lo > 1 ) { c.gridwidth = 1; gridBag.setConstraints(left,c); gridBag.setConstraints(right,c); add(left); add(right); } if ( parent == null ) { sorter = new Sorter(msa,this); } setActive(false); } public synchronized void start() { sorter.start(); if ( ! sorter.isAlive() ) { sorter = new Sorter(msa,this); sorter.start(); } } public synchronized void stop() { sorter.stop(); } // Don't call setInput unless the length stays the same. public synchronized void setInput( int maxVal, int intValues[], int lo, int hi ) { resetComparisonCount(); bp.setMaxValue(maxVal); for (int i=lo;i 1 ) { int mid = (lo+hi)/2; left.setInput(maxVal,intValues,lo,mid); right.setInput(maxVal,intValues,mid,hi); } if ( parent == null ) { rewindMaxVal = maxVal; rewindIntValues = intValues; rewindLo = lo; rewindHi = hi; } } public synchronized void rewindInput() { setInput(rewindMaxVal,rewindIntValues,rewindLo,rewindHi); resetComparisonCount(); } synchronized void sort(boolean pauseAtBeginning) throws InterruptedException, KillSortException { int L,R,w; int value; int mid = len/2; if ( pauseAtBeginning ) { ticker.pause(); } resetComparisonCount(); if ( parent != null ) { for (int i=0;i= comparisonUpperBound ) throw new RuntimeException(); // i.e. this can't happen. CCLabel.incrementCount(c); if ( parent != null ) parent.incrementCount(c); } void resetComparisonCount() { comparisonCount = 0; CCLabel.resetCount(); } public int getComparisonCount() { return comparisonCount; } // What to do when we're exposed. public void paint(Graphics g) { update(g); } public void update(Graphics g) { Dimension d = size(); // g.setColor(getBackground()); // g.fillRect(0,0,d.width-1,d.height-1); if ( isActive ) { g.setColor(getForeground()); } else { g.setColor(getBackground()); } g.drawRect(0,0,d.width-1,d.height-1); } public Insets insets() { return theseInsets; } public void rootUnsortedOnly() { if ( parent == null ) { setBarUnsortedAll(); } else { setBarInvisibleAll(); } if ( left != null ) { left.rootUnsortedOnly(); right.rootUnsortedOnly(); } comparisonCount = 0; } public void setActive( boolean b ) { isActive = b; repaint(); } public int getComparisonUpperBound() { return comparisonUpperBound; } } class Sorter extends Thread { MergeSortApp msa; MergeSortActivation msac; public Sorter(MergeSortApp msa, MergeSortActivation msac) { this.msa = msa; this.msac = msac; } public void run() { while ( true ) { try { msa.ticker.waitForGo(); msac.sort(false); msa.doneSorting(); } catch (InterruptedException e) { } catch (KillSortException e) { msa.ticker.stopForNow(); // Go from Killed to Stopped. } } } }