/*
* TV-Browser
* Copyright (C) 04-2003 Martin Oberhauser (darras@users.sourceforge.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* CVS information:
* $RCSfile$
* $Source$
* $Date: 2009-09-27 22:30:36 +0200 (Sun, 27 Sep 2009) $
* $Author: bananeweizen $
* $Revision: 5980 $
*/
package tvbrowser.ui.programtable.background;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.util.ArrayList;
import javax.swing.JComponent;
import tvbrowser.core.Settings;
import tvbrowser.ui.programtable.DefaultProgramTableModel;
import tvbrowser.ui.programtable.ProgramTableLayout;
import tvbrowser.ui.programtable.ProgramTableModel;
import util.ui.ImageUtilities;
import util.ui.ProgramPanel;
import util.ui.TimeFormatter;
import devplugin.Date;
import devplugin.Program;
/**
*
*
* @author Til Schneider, www.murfman.de
*/
public class TimeBlockBackPainter extends AbstractBackPainter {
private static final Font TABLE_WEST_FONT = new Font("Dialog", Font.PLAIN, 14);
private static final Color TABLE_WEST_FONT_COLOR = Color.DARK_GRAY;
private Image mBackgroundImage1, mBackgroundImage2;
private Image mTableWestImage1, mTableWestImage2;
private int mBlockSize;
private TimeBlock[] mBlockArr;
private JComponent mTableWest;
private TimeFormatter mFormatter;
public TimeBlockBackPainter() {
if (Settings.propTwelveHourFormat.getBoolean()) {
mFormatter = new TimeFormatter("hh a");
} else {
mFormatter = new TimeFormatter("HH");
}
mBackgroundImage1 = ImageUtilities
.createImageAsynchronous(Settings.propTimeBlockBackground1.getString());
mBackgroundImage2 = ImageUtilities
.createImageAsynchronous(Settings.propTimeBlockBackground2.getString());
mTableWestImage1 = ImageUtilities
.createImageAsynchronous(Settings.propTimeBlockWestImage1.getString());
mTableWestImage2 = ImageUtilities
.createImageAsynchronous(Settings.propTimeBlockWestImage2.getString());
if (Settings.propTimeBlockShowWest.getBoolean()) {
mTableWest = new TimeBlockTableWest();
} else {
mTableWest = null;
}
mBlockSize = Settings.propTimeBlockSize.getInt();
}
/**
* Is called when the table's layout has changed.
*/
public void layoutChanged(ProgramTableLayout layout, ProgramTableModel model) {
mBlockArr = createBlockArray(layout, model);
}
/**
* Paints the background.
*
* @param grp
* @param columnWidth
* @param tableHeight
* @param clipBounds
* @param layout
* The table's layout
* @param model
* The table model
*/
public void paintBackground(Graphics grp, int columnWidth, int tableHeight,
int minCol, int maxCol, Rectangle clipBounds, ProgramTableLayout layout,
ProgramTableModel model) {
// We make a local copy of the block y array to get thread safety
// (layoutChanged() may set mBlockYArr to null during paining)
TimeBlock[] blockArr = createBlockArray(layout, model);
boolean toggleFlag = true;
int minY;
int maxY = -1;
for (int i = 0; i < blockArr.length; i++) {
// Get the image of this time block
Image backImg;
if (toggleFlag) {
backImg = mBackgroundImage1;
} else {
backImg = mBackgroundImage2;
}
// Get the y positions of this time block
minY = blockArr[i].mStartY;
if ((i + 1) < blockArr.length) {
maxY = blockArr[i + 1].mStartY;
} else {
maxY = tableHeight;
}
// Paint the background of this time block
int x = minCol * columnWidth;
for (int col = minCol; col <= maxCol; col++) {
fillImage(grp, x, minY, columnWidth, (maxY - minY), backImg, clipBounds);
x += columnWidth;
}
// Toggle the background
toggleFlag = !toggleFlag;
}
// Paint the rest if needed
if (maxY < tableHeight) {
minY = maxY + 1;
maxY = tableHeight;
// Get the image of this time block
Image backImg;
if (toggleFlag) {
backImg = mBackgroundImage1;
} else {
backImg = mBackgroundImage2;
}
// Paint the background of this time block
int x = minCol * columnWidth;
for (int col = minCol; col <= maxCol; col++) {
fillImage(grp, x, minY, columnWidth, (maxY - minY), backImg, clipBounds);
x += columnWidth;
}
}
}
private TimeBlock[] createBlockArray(ProgramTableLayout layout,
ProgramTableModel model) {
int blockCount = 2 * 24 / mBlockSize;
TimeBlock[] blocks = new TimeBlock[blockCount];
for (int i = 0; i < blockCount; i++) {
blocks[i] = new TimeBlock(i * mBlockSize * 60);
}
// Go through the model and find the block borders
Date mainDate = ((DefaultProgramTableModel) model).getDate();
int columnCount = model.getColumnCount();
for (int col = 0; col < columnCount; col++) {
int y = layout.getColumnStart(col);
int rowCount = model.getRowCount(col);
for (int row = 0; row < rowCount; row++) {
ProgramPanel panel = model.getProgramPanel(col, row);
if (panel != null) {
Program prog = panel.getProgram();
int startTime = prog.getStartTime();
if (!mainDate.equals(prog.getDate())) {
startTime += 24 * 60;
}
// Go to the block of this program
int blockIndex = startTime / (mBlockSize * 60);
TimeBlock block = blocks[blockIndex];
// Check whether the y of the program is lower than the one of the
// block
int blockY = block.mStartY;
if ((blockY == -1) || (y < blockY)) {
block.mStartY = y;
}
y += panel.getHeight();
}
}
}
// Remove the blocks that have no y
ArrayList<TimeBlock> list = new ArrayList<TimeBlock>();
for (int i = 0; i < blockCount; i++) {
if (blocks[i].mStartY != -1) {
list.add(blocks[i]);
}
}
// Create an array
return list.toArray(new TimeBlock[list.size()]);
}
/**
* Gets the component that should be shown in the west of the table.
* <p>
* If nothing should be shown in the west, null is returned.
*
* @return The table west.
*/
public JComponent getTableWest() {
return mTableWest;
}
private static class TimeBlock {
public TimeBlock(int startTime) {
mStartTime = startTime;
mStartY = -1;
}
private int mStartTime;
private int mStartY;
} // class TimeBlock
class TimeBlockTableWest extends JComponent {
private FontMetrics mFontMetrics;
public TimeBlockTableWest() {
mFontMetrics = getFontMetrics(TABLE_WEST_FONT);
}
public Dimension getPreferredSize() {
int width = mFontMetrics.stringWidth(mFormatter.formatTime(23, 0)) + 4;
int height = 1000000; // We don't know the size
return new Dimension(width, height);
}
public void paintComponent(Graphics grp) {
// We make a local copy of the block y array to get thread savety
// (layoutChanged() may set mBlockYArr to null during paining)
TimeBlock[] blockArr = mBlockArr;
if ((blockArr != null) && (blockArr.length > 0)) {
boolean toggleFlag = false;
int width = getWidth();
int height = getHeight();
Rectangle clipBounds = grp.getClipBounds();
grp.setFont(TABLE_WEST_FONT);
grp.setColor(TABLE_WEST_FONT_COLOR);
for (int i = 0; i < blockArr.length; i++) {
toggleFlag = !toggleFlag;
// Get the y positions of this time block
int minY = blockArr[i].mStartY;
int maxY;
if ((i + 1) < blockArr.length) {
maxY = blockArr[i + 1].mStartY;
} else {
maxY = height;
}
if (!clipBounds.intersects(0, minY, width, maxY - minY)) {
// this piece is not visible at all
continue;
}
// Get the image of this time block
Image backImg;
if (toggleFlag) {
backImg = mTableWestImage1;
} else {
backImg = mTableWestImage2;
}
// Paint the block
fillImage(grp, 0, minY, width, (maxY - minY), backImg, clipBounds);
String msg = mFormatter.formatTime(blockArr[i].mStartTime / 60 % 24,
0);
int msgWidth = mFontMetrics.stringWidth(msg);
int x = width - msgWidth - 2;
grp.drawString(msg, x, minY + TABLE_WEST_FONT.getSize());
}
}
}
} // class TimeBlockTableWest
}