// Last edited on 2000-09-03 07:50:41 by stolfi import java.lang.Math; import java.awt.Graphics; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.Event; import java.awt.Panel; import java.awt.Scrollbar; import java.awt.BorderLayout; import java.awt.event.AdjustmentListener; import java.awt.event.AdjustmentEvent; import Planta; import Engenho; import Ouvidor; import PlinMapa; import PlinBarraDeAjuste; import Trecho; import Elemento; import Retangulo; class PlinMapaComBarras extends Panel implements Ouvidor { PlinMapa mapa; PlinBarraDeAjuste barraX; PlinBarraDeAjuste barraY; Retangulo rTudo, rFoco; InterfaceGrafica raiz; public PlinMapaComBarras(Engenho eng, Retangulo rT, InterfaceGrafica z) { raiz = z; rTudo = new Retangulo(rT.xMin, rT.xMax, rT.yMin, rT.yMax); setLayout(new BorderLayout()); barraX = new PlinBarraDeAjuste(Scrollbar.HORIZONTAL, this); add("South", barraX); barraY = new PlinBarraDeAjuste(Scrollbar.VERTICAL, this); add("East", barraY); mapa = new PlinMapa(eng,rTudo,z); add("Center", mapa); doLayout(); mudaFoco(rTudo); validate(); } // MÉTODOS PÚBLICOS - Podem ser chamados de contextos gerais public Retangulo pegaFoco() // Devolve o retângulo de interesse corrente. { return(rFoco); } public void mudaFoco(Retangulo r) // Define o retângulo de interesse, reposicionando as barras e // redesenhando o mapa. { rFoco = new Retangulo(r.xMin, r.xMax, r.yMin, r.yMax); cortaRetangulo(rFoco); raiz.mensagem("Foco = " + "[" + rFoco.xMin + ".." + rFoco.xMax + "]" + " × " + "[" + rFoco.yMin + ".." + rFoco.yMax + "]" ); mapa.mudaFoco(rFoco); mudaBarrasConformeFoco(); } public Graphics getMapaGraphics() // Devolve o contexto gráfico do mapa. O resultado só é válido // enquanto o estado da interface estiver congelado. { return mapa.getGraphics(); } // CALLBACKS public void avisa(Object causa) { if ((causa == barraX) || (causa == barraY)) { mudaFocoConformeBarras(); } } // MÉTODOS PRIVADOS private static Intervalo ivTmp = new Intervalo(); private void mudaFocoConformeBarras() { // Ajusta o retângulo de interesse a partir das barras de scroll: // Supõe que o tamanho do retângulo não varia. double xD = rTudo.xMax - rTudo.xMin; double xR = (rFoco.xMax - rFoco.xMin)/2; double yD = rTudo.yMax - rTudo.yMin; double yR = (rFoco.yMax - rFoco.yMin)/2; barraX.pegaIntervalo(ivTmp); double xC = rTudo.xMin + (ivTmp.min + ivTmp.max)/2.0 * xD; barraY.pegaIntervalo(ivTmp); double yC = rTudo.yMax - (ivTmp.min + ivTmp.max)/2.0 * yD; raiz.comandoMudarFoco(new Retangulo(xC-xR, xC+xR, yC-yR, yC+yR)); } private void mudaBarrasConformeFoco() // Posiciona as barras de scroll conforme retângulo de interesse: { barraX.mudaIntervalo(rTudo.xMin, rFoco.xMin, rFoco.xMax, rTudo.xMax); barraY.mudaIntervalo(rTudo.yMax, rFoco.yMax, rFoco.yMin, rTudo.yMin); } // Garante que o retângulo dado está dentro do retângulo global: // private void cortaRetangulo(Retangulo r) { if (r.xMin < rTudo.xMin) { r.xMin = rTudo.xMin; } if (r.xMax > rTudo.xMax) { r.xMax = rTudo.xMax; } if (r.yMin < rTudo.yMin) { r.yMin = rTudo.yMin; } if (r.yMax > rTudo.yMax) { r.yMax = rTudo.yMax; } } public Dimension getMinimumSize() { Dimension d = mapa.getPreferredSize(); return new Dimension(d.width + 20, d.height + 20); } public Dimension getPreferredSize() { return getMinimumSize(); } }