/* * iDART: The Intelligent Dispensing of Antiretroviral Treatment * Copyright (C) 2006 Cell-Life * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * 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 version * 2 for more details. * * You should have received a copy of the GNU General Public License version 2 * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package org.celllife.idart.gui.composite; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import model.manager.AdherenceManager; import model.manager.DrugManager; import org.apache.log4j.Logger; import org.celllife.idart.database.hibernate.Drug; import org.celllife.idart.database.hibernate.PackagedDrugs; import org.celllife.idart.database.hibernate.Packages; import org.celllife.idart.database.hibernate.PillCount; import org.celllife.idart.facade.PillCountFacade; import org.celllife.idart.gui.misc.iDARTChangeListener; import org.celllife.idart.gui.platform.GenericGuiInterface; import org.celllife.idart.gui.utils.ResourceUtils; import org.celllife.idart.gui.utils.iDartColor; import org.celllife.idart.gui.utils.iDartFont; import org.celllife.idart.misc.iDARTUtil; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TableEditor; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.hibernate.Session; /** * Table Composite * */ public class PillCountTable implements GenericGuiInterface { private Logger log = Logger.getLogger(PillCountTable.class); private Group grpPillCount; private Table theTable; private Label lblHeading; private TableColumn clmDrugName; private TableColumn clmInHand; private TableColumn clmPercent; private PillCountFacade pillFacade; private TableEditor editorTbl; private Packages previousPack; private Shell parent; Session hSession; private MouseListener mousAdapNoPillUseWaring; private iDARTChangeListener changeListener; private MouseListener tableEditorMouseAdaptor; /** * Constructor for PillCountTable. * * @param parent * Composite * @param style * int * @param session * Session * @param bounds * Rectangle */ public PillCountTable(Composite parent, int style, Session session, Rectangle bounds) { log.info("Creating PillCountTable"); this.parent = parent.getShell(); grpPillCount = new Group(parent, style); grpPillCount.setBounds(bounds); hSession = session; pillFacade = new PillCountFacade(session); grpPillCount.setFont(ResourceUtils.getFont(iDartFont.VERASANS_8)); grpPillCount.setText("Pill Count:"); Rectangle boundsForTable = new Rectangle(10, 20, bounds.width - 20, bounds.height - 30); createTable(boundsForTable); } /** * This constructor does not create a new group as you are already using a * group as a parent * * @param parent * @param style * @param session * @param boundsForTable * Rectangle */ public PillCountTable(Group parent, int style, Session session, Rectangle boundsForTable) { grpPillCount = parent; hSession = session; pillFacade = new PillCountFacade(session); createTable(boundsForTable); } /** * Method createTable. * * @param bounds * Rectangle */ public void createTable(Rectangle bounds) { theTable = new Table(grpPillCount, SWT.FULL_SELECTION | SWT.BORDER); theTable.setHeaderVisible(true); theTable.setLinesVisible(true); theTable.setBounds(bounds); theTable.setFont(ResourceUtils.getFont(iDartFont.VERASANS_8)); clmDrugName = new TableColumn(theTable, SWT.NONE); clmDrugName.setText("Drug Name"); clmDrugName.setWidth(((bounds.width - 20) * 65 / 100) - 10); clmDrugName.setResizable(true); clmInHand = new TableColumn(theTable, SWT.NONE); clmInHand.setText("Accum"); clmInHand.setWidth(((bounds.width - 20) * 20 / 100) + 5); clmInHand.setResizable(true); clmPercent = new TableColumn(theTable, SWT.NONE); clmPercent.setText("%"); clmPercent.setWidth(((bounds.width - 20) * 15 / 100) + 15); clmPercent.setResizable(true); lblHeading = new Label(grpPillCount, SWT.NONE); lblHeading.setBounds(new Rectangle(10, 3, bounds.width - 13, 13)); lblHeading.setFont(ResourceUtils.getFont(iDartFont.VERASANS_8_BOLD)); lblHeading.setForeground(ResourceUtils.getColor(iDartColor.BLACK)); lblHeading.setBackground(null); lblHeading.setVisible(false); } /** * Method setHeading. * * @param heading * String */ public void setHeading(String heading) { if (heading.length() > 0) { lblHeading.setText(heading); lblHeading.setVisible(true); } else { lblHeading.setText(heading); lblHeading.setVisible(false); } } /** * Method setBounds. * * @param x * int * @param y * int * @param width * int * @param height * int */ public void setBounds(int x, int y, int width, int height) { grpPillCount.setBounds(x, y, width, height); } public void clearTable() { theTable.clearAll(); theTable.removeAll(); } /** * Fill the last package table with the details of the ARV drugs in the last * package * * @param previousPack * Packages */ public void populateLastPackageDetails(@SuppressWarnings("hiding") Packages previousPack, Date datePacked) { this.previousPack = previousPack; clearTable(); disableIfUponFirstVisit(); if (previousPack != null) { java.util.Set<PillCount> previousPackPillCounts = pillFacade .getPillCountsReturnedFromThisPackage(previousPack); java.util.List<PackagedDrugs> packagedDrugsList = previousPack .getPackagedDrugs(); Iterator<PackagedDrugs> packDrugIt = packagedDrugsList.iterator(); // keep track of all drugs already in the list java.util.List<Drug> usedDrugs = new ArrayList<Drug>(); while (packDrugIt.hasNext()) { PackagedDrugs pd = packDrugIt.next(); if (pd != null) { Drug d = pd.getStock().getDrug(); if ((d.getSideTreatment() == 'F') && (!usedDrugs.contains(d))) { TableItem ti = new TableItem(theTable, SWT.NONE); if (theTable.getBounds().width < 300) ti.setText(0, DrugManager .getShortGenericDrugName(d, true)); else ti.setText(0, d.getName()); // search for existing pillcounts Iterator<PillCount> previousPackPillCountsItr = previousPackPillCounts .iterator(); while (previousPackPillCountsItr.hasNext()) { PillCount pc = previousPackPillCountsItr.next(); if (pc.getDrug().equals(d)) { pc.setDateOfCount(new Date()); ti.setData(pc); ti.setText(1, "" + pc.getAccum()); } } if (ti.getData() == null) // didn't find a previous pillcount { ti.setData(new PillCount(-1, previousPack, datePacked, d)); } usedDrugs.add(d); } else if ((d.getSideTreatment() == 'T') && (!usedDrugs.contains(d))) { TableItem ti = new TableItem(theTable, SWT.NONE); ti.setText(0, d.getName()); ti.setFont(ResourceUtils .getFont(iDartFont.VERASANS_8_ITALIC)); ti.setData(null); usedDrugs.add(d); } } } } } private void attachEditor() { // add a editor for the accum column // add a editor for the accum column editorTbl = new TableEditor(theTable); editorTbl.horizontalAlignment = SWT.LEFT; editorTbl.grabHorizontal = true; tableEditorMouseAdaptor = new MouseAdapter() { @Override public void mouseDown(MouseEvent event) { // Dispose any existing editor Control old = editorTbl.getEditor(); if (old != null) old.dispose(); // Determine where the mouse was clicked Point pt = new Point(event.x, event.y); // Determine which row was selected final TableItem item = theTable.getItem(pt); if (item != null) { // Determine which column was selected int column = -1; for (int i = 0, n = theTable.getColumnCount(); i < n; i++) { Rectangle rect = item.getBounds(i); if (rect.contains(pt)) { // This is the selected column column = i; break; } } if ((column == 1) && (item.getData() != null)) { // Create the Text object for our editor final Text text = new Text(theTable, SWT.NONE); text.setForeground(item.getForeground()); text.setBackground(ResourceUtils .getColor(iDartColor.GRAY)); text.setFont(ResourceUtils .getFont(iDartFont.VERASANS_8)); text.setText(item.getText(column)); text.setForeground(item.getForeground()); text.selectAll(); text.setFocus(); editorTbl.minimumWidth = text.getBounds().width; // Set the control into the editor editorTbl.setEditor(text, item, column); final int col = column; text.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent event1) { String oldValue = item.getText(col); item.setText(col, text.getText()); // check user input if (!text.getText().trim().equals(oldValue)) { if (!updateAdherance(item, text.getText(), col)) { text.setText(""); } fireChangeEvent(item.getData()); } } }); text.addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent event1) { theTable.setSelection(theTable.getItemCount()); text.dispose(); } @Override public void focusGained(FocusEvent event1) { } }); } } } }; theTable.addMouseListener(tableEditorMouseAdaptor); } /** * Method updateAdherance. * * @param item * TableItem * @param text * String * @param col * int * @return boolean */ private boolean updateAdherance(final TableItem item, String text, final int col) { try { int accum = Integer.parseInt(text); return updateAdherence(item, accum, col); } catch (NumberFormatException e) { ((PillCount) item.getData()).setAccum(-1); java.awt.Toolkit.getDefaultToolkit().beep(); item.setText(col, ""); ((PillCount) item.getData()).setAccum(-1); item.setBackground(col + 1, ResourceUtils .getColor(iDartColor.LIST_BACKGROUND)); return false; } } /** * Method updateAdherence. * * @param item * TableItem * @param accum * Integer * @param col * int * @return boolean */ private boolean updateAdherence(final TableItem item, Integer accum, final int col) { if (accum > -1){ int adherencePercent = AdherenceManager.getAdherencePercent(hSession, accum, ((PillCount) item.getData())); item.setText(col + 1, "" + adherencePercent); setColourForAdherencePercentCell(item, 2, adherencePercent); ((PillCount) item.getData()).setAccum(accum); } return true; } /** * Method getTable. * * @return Table */ public Table getTable() { return theTable; } public void removeEditor() { if (editorTbl != null) editorTbl.dispose(); } public void addPillCountWarning(final String message) { mousAdapNoPillUseWaring = new MouseAdapter() { @Override public void mouseDown(MouseEvent event) { MessageBox msg = new MessageBox(parent, SWT.DIALOG_TRIM); msg.setText("Pill Count Table Editor Warning"); msg.setMessage(message); msg.open(); } }; theTable.addMouseListener(mousAdapNoPillUseWaring); } private void disableIfUponFirstVisit() { Date previousPackDate; long numOfDays = 0; removeTableAdaptor(tableEditorMouseAdaptor); removeTableAdaptor(mousAdapNoPillUseWaring); if (previousPack != null) { previousPackDate = previousPack.getPickupDate(); numOfDays = iDARTUtil.getDaysBetween(previousPackDate, new Date()); if (numOfDays <= 0) { addPillCountWarning("The pill count table has been disabled because the patient received their last package today." + "\n\nIf you wish to record a pill count from the previous package please delete " + "the most recent package for the patient, " + "then record the pill count and re-dispense the package that was deleted."); } else { attachEditor(); } } else { log.debug("Previous pack is null"); addPillCountWarning("The pill count table has been disabled because the patient has " + "not received any previous packages. \n\nYou will be able to do " + "a pill count for this patient when they receive their next package."); } } /** * @param tableEditorMouseAdaptor2 */ private void removeTableAdaptor(MouseListener tableEditorMouseAdaptor2) { if (tableEditorMouseAdaptor2 != null) theTable.removeMouseListener(tableEditorMouseAdaptor2); } /** * Method getPillCounts. * * @return Set<PillCount> */ public Set<PillCount> getPillCounts() { java.util.Set<PillCount> pcsToSave = new HashSet<PillCount>(); if (previousPack == null) return pcsToSave; previousPack.getPillCounts().clear(); for (int i = 0; i < theTable.getItemCount(); i++) { if (theTable.getItem(i).getData() != null) { PillCount pc = (PillCount) theTable.getItem(i).getData(); if (pc.getAccum() != -1) { if (pc.getDateOfCount() == null) { pc.setDateOfCount(new Date()); } pc.setPreviousPackage(previousPack); pcsToSave.add(pc); } } } previousPack.getPillCounts().addAll(pcsToSave); return previousPack.getPillCounts(); } /** * Method setColourForAdherencePercentCell. * * @param item * TableItem * @param cell * int * @param adherencePercent * int */ private void setColourForAdherencePercentCell(TableItem item, int cell, int adherencePercent) { if (adherencePercent >= 95) { item.setBackground(cell, ResourceUtils.getColor(iDartColor.GREEN)); } else if (adherencePercent >= 90) { item.setBackground(cell, ResourceUtils.getColor(iDartColor.YELLOW)); } else { item.setBackground(cell, ResourceUtils.getColor(iDartColor.RED)); } } /** * Update the pillcounts given a new dateOfCount. * * @param dispenseDate */ public void update(Date dateOfCount) { TableItem[] items = theTable.getItems(); for (TableItem item : items) { PillCount pc = (PillCount) item.getData(); if (pc != null) { pc.setDateOfCount(dateOfCount); updateAdherence(item, pc.getAccum(), 1); } } } /** * Method addChangeListener. * * @param listener * iDARTChangeListener */ public void addChangeListener(iDARTChangeListener listener) { this.changeListener = listener; } /** * Method fireChangeEvent. * * @param o * Object */ private void fireChangeEvent(Object o) { if (changeListener != null) changeListener.changed(o); } /** * Method setPillCountGroupHeading. * * @param txt * String */ public void setPillCountGroupHeading(String txt) { grpPillCount.setText(txt); } /** * Method getHSession. * * @return Session */ public Session getHSession() { return hSession; } /** * Method setHSession. * * @param session * Session */ public void setHSession(Session session) { hSession = session; } }