001/* [{ 002Copyright 2007-2011 Nicolas Carranza <nicarran at gmail.com> 003 004This file is part of jpen. 005 006jpen is free software: you can redistribute it and/or modify 007it under the terms of the GNU Lesser General Public License as published by 008the Free Software Foundation, either version 3 of the License, 009or (at your option) any later version. 010 011jpen is distributed in the hope that it will be useful, 012but WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014GNU Lesser General Public License for more details. 015 016You should have received a copy of the GNU Lesser General Public License 017along with jpen. If not, see <http://www.gnu.org/licenses/>. 018}] */ 019package jpen.owner; 020 021import jpen.event.PenAdapter; 022import jpen.event.PenListener; 023import jpen.PButtonEvent; 024import jpen.Pen; 025import jpen.PenEvent; 026 027/** 028Provides a mechanism to start/stop the drag-out operation. 029*/ 030public abstract class AbstractPenOwner 031 implements PenOwner{ 032 033 protected PenManagerHandle penManagerHandle; 034 private boolean isDraggingOut; // state: true when dragging outside the component 035 private final PenListener draggingOutPenListener=new PenAdapter(){ 036 @Override 037 public void penButtonEvent(PButtonEvent ev){ 038 synchronized(penManagerHandle.getPenSchedulerLock()){ 039 if(!ev.button.value && 040 !getPen().hasPressedButtons() && 041 isDraggingOut 042 ){ 043 stopDraggingOut(); 044 draggingOutDisengaged(); 045 } 046 } 047 } 048 }; 049 050 /** 051 Force stopping a drag-out operation if it was in progress. This method must be called when entering the {@link PenClip} to stop the drag-out operation if it was still in progress. 052 053 This method must be called while holding the {@link jpen.owner.PenOwner.PenManagerHandle#getPenSchedulerLock()} (See {@link PenOwner#isDraggingOut()}). 054 055 @return {@code true} if a drag-out operation was in progress and was stopped. 056 */ 057 protected final boolean stopDraggingOut(){ 058 if(!isDraggingOut) 059 return false; 060 isDraggingOut=false; 061 getPen().removeListener(draggingOutPenListener); 062 return true; 063 } 064 065 protected abstract void draggingOutDisengaged(); 066 067 /** 068 Starts a drag-out operation if there are pressed buttons and installs a penListener which automatically stops the drag-out operation when all the buttons are unpressed. 069 070 This method must be called while holding the {@link jpen.owner.PenOwner.PenManagerHandle#getPenSchedulerLock()} (See {@link PenOwner#isDraggingOut()}). 071 072 @return {@code true} if a drag-out operation was started or was already in progress. 073 */ 074 protected final boolean startDraggingOut(){ 075 if(isDraggingOut) 076 return true; 077 if(!getPen().hasPressedButtons()) 078 return false; 079 isDraggingOut=true; 080 getPen().addListener(draggingOutPenListener); 081 return true; 082 } 083 084 //@Override 085 public final void setPenManagerHandle(PenManagerHandle penManagerHandle){ 086 if(this.penManagerHandle!=null) 087 throw new IllegalStateException("The penManagerHandle has already being set. This PenOwner can't be used on multiple PenManagers."); 088 this.penManagerHandle=penManagerHandle; 089 init(); 090 } 091 092 /** 093 Override this method to do initialization. This method is called after the {@link #penManagerHandle} is set. 094 */ 095 protected abstract void init(); 096 097 //@Override 098 public final boolean isDraggingOut(){ 099 return isDraggingOut; 100 } 101 102 protected final Pen getPen(){ 103 return penManagerHandle.getPenManager().pen; 104 } 105 106 //@Override 107 public Object evalPenEventTag(PenEvent ev){ 108 return null; 109 } 110 111 //@Override 112 public boolean enforceSinglePenManager(){ 113 return false; 114 } 115 116}