/*******************************************************************************
* Copyright (c) 2006-2010, G. Weirich and Elexis
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* G. Weirich - initial implementation
*
*******************************************************************************/
package ch.elexis.core.ui.views;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IFontProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.part.ViewPart;
import ch.elexis.admin.AccessControlDefaults;
import ch.elexis.core.constants.Preferences;
import ch.elexis.core.data.activator.CoreHub;
import ch.elexis.core.data.events.ElexisEvent;
import ch.elexis.core.data.events.ElexisEventDispatcher;
import ch.elexis.core.data.events.ElexisEventListener;
import ch.elexis.core.data.events.Heartbeat.HeartListener;
import ch.elexis.core.lock.types.LockResponse;
import ch.elexis.core.model.issue.Priority;
import ch.elexis.core.model.issue.ProcessStatus;
import ch.elexis.core.model.issue.Type;
import ch.elexis.core.model.issue.Visibility;
import ch.elexis.core.ui.UiDesk;
import ch.elexis.core.ui.actions.GlobalEventDispatcher;
import ch.elexis.core.ui.actions.IActivationListener;
import ch.elexis.core.ui.actions.RestrictedAction;
import ch.elexis.core.ui.dialogs.ReminderDetailDialog;
import ch.elexis.core.ui.events.ElexisUiEventListenerImpl;
import ch.elexis.core.ui.icons.Images;
import ch.elexis.core.ui.locks.AcquireLockBlockingUi;
import ch.elexis.core.ui.locks.ILockHandler;
import ch.elexis.core.ui.locks.LockResponseHelper;
import ch.elexis.core.ui.util.SWTHelper;
import ch.elexis.core.ui.util.ViewMenus;
import ch.elexis.core.ui.util.viewers.CommonContentProviderAdapter;
import ch.elexis.core.ui.util.viewers.CommonViewer;
import ch.elexis.core.ui.util.viewers.DefaultLabelProvider;
import ch.elexis.core.ui.util.viewers.SimpleWidgetProvider;
import ch.elexis.core.ui.util.viewers.ViewerConfigurer;
import ch.elexis.data.Anwender;
import ch.elexis.data.Patient;
import ch.elexis.data.PersistentObject;
import ch.elexis.data.Query;
import ch.elexis.data.Reminder;
import ch.rgw.io.Settings;
import ch.rgw.tools.TimeTool;
public class ReminderView extends ViewPart implements IActivationListener, HeartListener {
public static final String ID = "ch.elexis.reminderview"; //$NON-NLS-1$
private IAction newReminderAction, deleteReminderAction, showOnlyOwnDueReminderToggleAction,
showSelfCreatedReminderAction, toggleAutoSelectPatientAction;
private RestrictedAction showOthersRemindersAction;
private RestrictedAction selectPatientAction;
private boolean bVisible;
private boolean autoSelectPatient;
private ReminderLabelProvider reminderLabelProvider = new ReminderLabelProvider();
private IAction filterActionType[] = new IAction[Type.values().length];
private Set<Integer> filterActionSet = new HashSet<Integer>();
private long cvHighestLastUpdate = 0l;
private boolean showOnlyDueReminders =
CoreHub.userCfg.get(Preferences.USR_REMINDERSOPEN, false);
private boolean showOthersReminders =
(CoreHub.userCfg.get(Preferences.USR_REMINDEROTHERS, false)
&& CoreHub.acl.request(AccessControlDefaults.ADMIN_VIEW_ALL_REMINDERS));
private boolean showSelfCreatedReminders =
CoreHub.userCfg.get(Preferences.USR_REMINDEROWN, false);
// 1079 - nur wenn der View offen ist werden bei Patienten-Wechsel die Reminders abgefragt!
private ElexisEventListener eeli_pat = new ElexisUiEventListenerImpl(Patient.class) {
public void runInUi(final ElexisEvent ev){
if (((Patient) ev.getObject()).equals(actPatient)) {
return;
}
actPatient = (Patient) ev.getObject();
if (bVisible) {
cv.notify(CommonViewer.Message.update);
}
if (!CoreHub.userCfg.get(Preferences.USR_SHOWPATCHGREMINDER, true)) {
UiDesk.asyncExec(new Runnable() {
public void run(){
List<Reminder> list = Reminder.findRemindersDueFor((Patient) ev.getObject(),
CoreHub.actUser, true);
if (list.size() != 0) {
StringBuilder sb = new StringBuilder();
for (Reminder r : list) {
sb.append(r.getMessage()).append("\n\n"); //$NON-NLS-1$
}
SWTHelper.alert(Messages.ReminderView_importantRemindersCaption,
sb.toString());
}
}
});
}
}
};
private ElexisEventListener eeli_user =
new ElexisUiEventListenerImpl(Anwender.class, ElexisEvent.EVENT_USER_CHANGED) {
public void runInUi(ElexisEvent ev){
boolean bChecked = CoreHub.userCfg.get(Preferences.USR_REMINDERSOPEN, true);
showOnlyOwnDueReminderToggleAction.setChecked(bChecked);
showSelfCreatedReminderAction
.setChecked(CoreHub.userCfg.get(Preferences.USR_REMINDEROWN, false));
// get state from user's configuration
showOthersRemindersAction
.setChecked(CoreHub.userCfg.get(Preferences.USR_REMINDEROTHERS, false));
// update action's access rights
showOthersRemindersAction.reflectRight();
reminderLabelProvider.updateUserConfiguration();
if (bVisible) {
cv.notify(CommonViewer.Message.update);
}
}
};
private ElexisEventListener eeli_reminder = new ElexisUiEventListenerImpl(Reminder.class,
ElexisEvent.EVENT_RELOAD | ElexisEvent.EVENT_CREATE | ElexisEvent.EVENT_UPDATE) {
public void catchElexisEvent(ElexisEvent ev){
cv.notify(CommonViewer.Message.update);
}
};
final CommonViewer cv;
ViewerConfigurer vc;
Query<Reminder> qbe;
Settings cfg;
ReminderFilter filter;
private Patient actPatient;
public ReminderView(){
cv = new CommonViewer();
qbe = new Query<Reminder>(Reminder.class);
Patient.load("0");
}
@Override
public void createPartControl(final Composite parent){
reminderLabelProvider.updateUserConfiguration();
filter = new ReminderFilter();
vc = new ViewerConfigurer(new CommonContentProviderAdapter() {
@Override
public Object[] getElements(final Object inputElement){
// Display reminders only if one is logged in
if (CoreHub.actUser == null) {
return new Object[0];
}
SortedSet<Reminder> reminders = new TreeSet<Reminder>();
if (showOthersReminders
&& CoreHub.acl.request(AccessControlDefaults.ADMIN_VIEW_ALL_REMINDERS)) {
qbe.clear();
reminders.addAll(qbe.execute());
} else {
reminders.addAll(Reminder.findOpenRemindersResponsibleFor(CoreHub.actUser,
showOnlyDueReminders, null, false));
if (showSelfCreatedReminders) {
qbe.clear();
qbe.add(Reminder.CREATOR, Query.EQUALS, CoreHub.actUser.getId());
qbe.or();
qbe.add(Reminder.RESPONSIBLE, Query.EQUALS, CoreHub.actUser.getId());
reminders.addAll(qbe.execute());
}
}
if (filterActionSet.size() > 0) {
reminders.removeIf(
p -> (filterActionSet.contains(p.getActionType().numericValue())));
}
return reminders.toArray();
}
}, reminderLabelProvider, null, new ViewerConfigurer.DefaultButtonProvider(),
new SimpleWidgetProvider(SimpleWidgetProvider.TYPE_LAZYLIST, SWT.MULTI, cv));
makeActions();
IAction[] list = new IAction[] {
newReminderAction, deleteReminderAction, null, showOnlyOwnDueReminderToggleAction,
showSelfCreatedReminderAction, showOthersRemindersAction, null
};
List<IAction> actionList = new ArrayList<IAction>();
actionList.addAll(Arrays.asList(list));
actionList.addAll(Arrays.asList(filterActionType));
actionList.add(null);
actionList.add(selectPatientAction);
ViewMenus menu = new ViewMenus(getViewSite());
menu.createToolbar(newReminderAction, toggleAutoSelectPatientAction);
menu.createMenu(actionList.toArray(new IAction[] {}));
if (CoreHub.acl.request(AccessControlDefaults.ADMIN_VIEW_ALL_REMINDERS)) {
showOthersRemindersAction.setEnabled(true);
showOthersRemindersAction
.setChecked(CoreHub.userCfg.get(Preferences.USR_REMINDEROTHERS, false));
} else {
showOthersRemindersAction.setEnabled(false);
}
cv.create(vc, parent, SWT.NONE, getViewSite());
cv.addDoubleClickListener(new CommonViewer.DoubleClickListener() {
public void doubleClicked(final PersistentObject obj, final CommonViewer cv){
Reminder reminder = (Reminder) obj;
AcquireLockBlockingUi.aquireAndRun(reminder, new ILockHandler() {
@Override
public void lockAcquired(){
ReminderDetailDialog rdd =
new ReminderDetailDialog(UiDesk.getTopShell(), (Reminder) obj);
int retVal = rdd.open();
if (retVal == Dialog.OK) {
ElexisEventDispatcher.getInstance().fire(
new ElexisEvent(reminder, getClass(), ElexisEvent.EVENT_UPDATE));
}
}
@Override
public void lockFailed(){
cv.notify(CommonViewer.Message.update);
}
});
}
});
menu.createViewerContextMenu(cv.getViewerWidget(), actionList.toArray(new IAction[] {}));
cv.getViewerWidget().addFilter(filter);
GlobalEventDispatcher.addActivationListener(this, getViewSite().getPart());
cv.getViewerWidget().addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event){
IStructuredSelection selection = (IStructuredSelection) event.getSelection();
selectPatientAction.setEnabled(selection.size() <= 1);
selectPatientAction.reflectRight();
if (autoSelectPatient && selectPatientAction.isEnabled()) {
selectPatientAction.doRun();
}
}
});
}
@Override
public void setFocus(){}
@Override
public void dispose(){
GlobalEventDispatcher.removeActivationListener(this, getViewSite().getPart());
CoreHub.userCfg.set(Preferences.USR_REMINDERSOPEN,
showOnlyOwnDueReminderToggleAction.isChecked());
}
private Images determineActionTypeImage(Type actionType){
switch (actionType) {
case PRINT:
case PRINT_DRUG_STICKER:
return Images.IMG_PRINTER;
case MAKE_APPOINTMENT:
return Images.IMG_CALENDAR;
case DISPENSE_MEDICATION:
return Images.IMG_PILL;
case PROCESS_SERVICE_RECORDING:
return Images.IMG_MONEY;
case CHECK_LAB_RESULT:
case READ_DOCUMENT:
return Images.IMG_EYE_WO_SHADOW;
case SEND_DOCUMENT:
return Images.IMG_MAIL_SEND;
default:
return Images.IMG_EMPTY_TRANSPARENT;
}
}
class ReminderLabelProvider extends DefaultLabelProvider
implements IColorProvider, IFontProvider {
private Font boldFont;
private Color colorDue;
private Color colorOverdue;
private Color colorOpen;
public Color getBackground(final Object element){
if (element instanceof Reminder) {
ProcessStatus stat = ((Reminder) element).getStatus();
if (stat == ProcessStatus.DUE) {
return colorDue;
} else if (stat == ProcessStatus.OVERDUE) {
return colorOverdue;
} else if (stat == ProcessStatus.OPEN) {
return colorOpen;
} else {
return null;
}
}
return null;
}
public void updateUserConfiguration(){
cfg = CoreHub.userCfg.getBranch(Preferences.USR_REMINDERCOLORS, true);
colorDue = UiDesk.getColorFromRGB(cfg.get(ProcessStatus.DUE.getLocaleText(), "FFFFFF")); //$NON-NLS-1$;
colorOverdue =
UiDesk.getColorFromRGB(cfg.get(ProcessStatus.OVERDUE.getLocaleText(), "FF0000")); //$NON-NLS-1$
colorOpen =
UiDesk.getColorFromRGB(cfg.get(ProcessStatus.OPEN.getLocaleText(), "00FF00")); //$NON-NLS-1$
}
public Color getForeground(final Object element){
Reminder reminder = (Reminder) element;
Priority prio = reminder.getPriority();
if (Priority.LOW == prio) {
return UiDesk.getColor(UiDesk.COL_GREY);
}
return null;
}
@Override
public Image getColumnImage(Object element, int columnIndex){
Reminder reminder = (Reminder) element;
Type actionType = reminder.getActionType();
return determineActionTypeImage(actionType).getImage();
}
@Override
public String getColumnText(Object element, int column){
Reminder reminder = (Reminder) element;
ProcessStatus status = reminder.getStatus();
if (ProcessStatus.CLOSED == status) {
return "[" + status.getLocaleText() + "] " + super.getText(element);
}
return super.getText(element);
}
@Override
public Font getFont(Object element){
Reminder reminder = (Reminder) element;
if (boldFont == null) {
Display disp = Display.getCurrent();
Font defaultFont = cv.getViewerWidget().getControl().getFont();
FontDescriptor boldDescriptor =
FontDescriptor.createFrom(defaultFont).setStyle(SWT.BOLD);
boldFont = boldDescriptor.createFont(disp);
}
Priority prio = reminder.getPriority();
if (Priority.HIGH == prio) {
return boldFont;
}
return null;
}
}
private void makeActions(){
newReminderAction = new Action(Messages.ReminderView_newReminderAction) { //$NON-NLS-1$
{
setImageDescriptor(Images.IMG_NEW.getImageDescriptor());
setToolTipText(Messages.ReminderView_newReminderToolTip); //$NON-NLS-1$
}
@Override
public void run(){
ReminderDetailDialog erd = new ReminderDetailDialog(getViewSite().getShell(), null);
int retVal = erd.open();
if (retVal == Dialog.OK) {
Reminder reminder = erd.getReminder();
CoreHub.getLocalLockService().acquireLock(reminder);
CoreHub.getLocalLockService().releaseLock(reminder);
}
cv.notify(CommonViewer.Message.update_keeplabels);
}
};
deleteReminderAction = new Action(Messages.ReminderView_deleteAction) { //$NON-NLS-1$
{
setImageDescriptor(Images.IMG_DELETE.getImageDescriptor());
setToolTipText(Messages.ReminderView_deleteToolTip); //$NON-NLS-1$
}
@Override
public void run(){
Object[] selections = cv.getSelection();
if ((selections != null) && (selections.length > 0)) {
for (Object sel : selections) {
Reminder r = (Reminder) sel;
LockResponse lockResponse = CoreHub.getLocalLockService().acquireLock(r);
if (lockResponse.isOk()) {
r.delete();
CoreHub.getLocalLockService().releaseLock(r);
} else {
LockResponseHelper.showInfo(lockResponse, r, null);
}
}
cv.notify(CommonViewer.Message.update_keeplabels);
}
}
};
showOnlyOwnDueReminderToggleAction =
new Action(Messages.ReminderView_onlyDueAction, Action.AS_CHECK_BOX) { //$NON-NLS-1$
{
setToolTipText(Messages.ReminderView_onlyDueToolTip); //$NON-NLS-1$
}
@Override
public void run(){
showOnlyDueReminders = showOnlyOwnDueReminderToggleAction.isChecked();
CoreHub.userCfg.set(Preferences.USR_REMINDERSOPEN, showOnlyDueReminders);
cv.notify(CommonViewer.Message.update_keeplabels);
}
};
showSelfCreatedReminderAction =
new Action(Messages.ReminderView_myRemindersAction, Action.AS_CHECK_BOX) { //$NON-NLS-1$
{
setToolTipText(Messages.ReminderView_myRemindersToolTip); //$NON-NLS-1$
}
@Override
public void run(){
showSelfCreatedReminders = showSelfCreatedReminderAction.isChecked();
CoreHub.userCfg.set(Preferences.USR_REMINDEROWN, showSelfCreatedReminders);
cv.notify(CommonViewer.Message.update_keeplabels);
}
};
showOthersRemindersAction =
new RestrictedAction(AccessControlDefaults.ADMIN_VIEW_ALL_REMINDERS,
Messages.ReminderView_foreignAction, Action.AS_CHECK_BOX) {
{
setToolTipText(Messages.ReminderView_foreignTooltip);
setImageDescriptor(Images.IMG_ACHTUNG.getImageDescriptor());
}
@Override
public void doRun(){
showOthersReminders = showOthersRemindersAction.isChecked();
CoreHub.userCfg.set(Preferences.USR_REMINDEROTHERS, showOthersReminders);
cv.notify(CommonViewer.Message.update_keeplabels);
}
};
selectPatientAction = new RestrictedAction(AccessControlDefaults.PATIENT_DISPLAY,
Messages.ReminderView_activatePatientAction, Action.AS_UNSPECIFIED) {
{
setImageDescriptor(Images.IMG_PERSON.getImageDescriptor());
setToolTipText(Messages.ReminderView_activatePatientTooltip);
}
public void doRun(){
Object[] sel = cv.getSelection();
if (sel != null && sel.length > 1) {
SWTHelper.showInfo(Messages.ReminderView_onePatOnly,
Messages.ReminderView_onlyOnePatientForActivation);
} else if (sel != null && sel.length > 0) {
Reminder reminder = (Reminder) sel[0];
Patient patient = reminder.getKontakt();
Anwender creator = reminder.getCreator();
if (patient != null) {
if (!patient.getId().equals(creator.getId())) {
ElexisEventDispatcher.fireSelectionEvent(patient);
}
}
}
}
};
toggleAutoSelectPatientAction =
new Action(Messages.ReminderView_activatePatientAction, Action.AS_CHECK_BOX) {
{
setImageDescriptor(Images.IMG_PERSON.getImageDescriptor());
setToolTipText(Messages.ReminderView_toggleSelectPatientActionTooltip);
autoSelectPatient =
CoreHub.userCfg.get(Preferences.USR_REMINDER_AUTO_SELECT_PATIENT, false);
setChecked(autoSelectPatient);
}
@Override
public void run(){
autoSelectPatient = toggleAutoSelectPatientAction.isChecked();
CoreHub.userCfg.set(Preferences.USR_REMINDER_AUTO_SELECT_PATIENT,
autoSelectPatient);
}
};
for (int i = 0; i < Type.values().length; i++) {
Type type = Type.values()[i];
filterActionType[i] = new Action(type.getLocaleText(), Action.AS_CHECK_BOX) {
@Override
public void run(){
if (isChecked()) {
filterActionSet.add(type.numericValue());
} else {
filterActionSet.remove(type.numericValue());
}
cv.notify(CommonViewer.Message.update_keeplabels);
}
};
filterActionType[i].setChecked(filterActionSet.contains(type.numericValue()));
filterActionType[i]
.setImageDescriptor(determineActionTypeImage(type).getImageDescriptor());
}
}
public void activation(final boolean mode){
/* egal */
}
public void visible(final boolean mode){
bVisible = mode;
if (mode) {
ElexisEventDispatcher.getInstance().addListeners(eeli_pat, eeli_user, eeli_reminder);
CoreHub.heart.addListener(this);
heartbeat();
} else {
ElexisEventDispatcher.getInstance().removeListeners(eeli_pat, eeli_user, eeli_reminder);
CoreHub.heart.removeListener(this);
}
}
public void heartbeat(){
long highestLastUpdate = PersistentObject.getHighestLastUpdate(Reminder.TABLENAME);
if (highestLastUpdate > cvHighestLastUpdate) {
cv.notify(CommonViewer.Message.update);
cvHighestLastUpdate = highestLastUpdate;
}
}
class ReminderFilter extends ViewerFilter {
@Override
public boolean select(final Viewer viewer, final Object parentElement,
final Object element){
if (element instanceof Reminder) {
Reminder check = (Reminder) element;
if (showOnlyOwnDueReminderToggleAction.isChecked()) {
if (check.getDateDue().isAfter(new TimeTool())) {
return false;
}
if (check.getStatus().ordinal() > 2) {
return false;
}
}
Patient act = ElexisEventDispatcher.getSelectedPatient();
if (act != null) {
String[] vals = check.get(true, Reminder.KONTAKT_ID, Reminder.FLD_VISIBILITY);
if (!vals[0].equals(act.getId())) {
if (Visibility.byNumericSafe(vals[1]) != Visibility.ALWAYS) {
return false;
}
}
}
}
return true;
}
}
}