Skip to content

Commit

Permalink
GH-25 only ask to save document if changes were user initiated. (#183)
Browse files Browse the repository at this point in the history
  • Loading branch information
pcorless authored Apr 13, 2021
1 parent 18fa9da commit 919f2b2
Show file tree
Hide file tree
Showing 33 changed files with 1,945 additions and 1,876 deletions.
18 changes: 9 additions & 9 deletions core/core-awt/src/main/java/org/icepdf/core/pobjects/Page.java
Original file line number Diff line number Diff line change
Expand Up @@ -812,10 +812,12 @@ public Shape getPageShape(int boundary, float userRotation, float userZoom) {
* the method @link{#createAnnotation} for creating new annotations.
*
* @param newAnnotation annotation object to add
* @param isNew annotation is new and should be added to stateManager, otherwise change will be part of the document
* but not yet added to the stateManager as the change was likely a missing content stream or popup.
* @return reference to annotation that was added.
*/
@SuppressWarnings("unchecked")
public Annotation addAnnotation(Annotation newAnnotation) {
public Annotation addAnnotation(Annotation newAnnotation, boolean isNew) {

// make sure the page annotations have been initialized.
if (annotations == null) {
Expand All @@ -839,20 +841,18 @@ public Annotation addAnnotation(Annotation newAnnotation) {
// update annots dictionary with new annotations reference,
annotations.add(newAnnotation.getPObjectReference());
// add the page as state change
stateManager.addChange(
new PObject(this, this.getPObjectReference()));
stateManager.addChange(new PObject(this, this.getPObjectReference()), isNew);
} else if (isAnnotAReference && annotations != null) {
// get annots array from page
// update annots dictionary with new annotations reference,
annotations.add(newAnnotation.getPObjectReference());
// add the annotations reference dictionary as state has changed
stateManager.addChange(
new PObject(annotations, library.getObjectReference(
entries, ANNOTS_KEY)));
new PObject(annotations, library.getObjectReference(entries, ANNOTS_KEY)), isNew);
}
// we need to add the a new annots reference
else {
List<Reference> annotsVector = new ArrayList(4);
List<Reference> annotsVector = new ArrayList<>(4);
annotsVector.add(newAnnotation.getPObjectReference());

// create a new Dictionary of annotations using an external reference
Expand All @@ -866,8 +866,8 @@ public Annotation addAnnotation(Annotation newAnnotation) {

// add the page and the new dictionary to the state change
stateManager.addChange(
new PObject(this, this.getPObjectReference()));
stateManager.addChange(annotsPObject);
new PObject(this, this.getPObjectReference()), isNew);
stateManager.addChange(annotsPObject, isNew);

this.annotations = new ArrayList<>();
}
Expand All @@ -883,7 +883,7 @@ public Annotation addAnnotation(Annotation newAnnotation) {
library.addObject(newAnnotation, newAnnotation.getPObjectReference());

// finally add the new annotations to the state manager
stateManager.addChange(new PObject(newAnnotation, newAnnotation.getPObjectReference()));
stateManager.addChange(new PObject(newAnnotation, newAnnotation.getPObjectReference()), isNew);

// return to caller for further manipulations.
return newAnnotation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class StateManager {
Logger.getLogger(StateManager.class.getName());

// a list is all we might need.
private final HashMap<Reference, PObject> changes;
private final HashMap<Reference, Change> changes;

// access to xref size and next revision number.
private final PTrailer trailer;
Expand Down Expand Up @@ -80,7 +80,18 @@ public Reference getNewReferenceNumber() {
* @param pObject object to add to cache.
*/
public void addChange(PObject pObject) {
changes.put(pObject.getReference(), pObject);
addChange(pObject, true);
}

/**
* Add a new PObject containing changed data to the cache.
*
* @param pObject object to add to cache.
* @param isNew new indicates a new object that should be saved when isChanged() is called. If false the object
* was added but because the object wasn't present for rendering and was created by the core library.
*/
public void addChange(PObject pObject, boolean isNew) {
changes.put(pObject.getReference(), new Change(pObject, isNew));
int objectNumber = pObject.getReference().getObjectNumber();
// check the reference numbers
synchronized (this) {
Expand Down Expand Up @@ -121,10 +132,25 @@ public void removeChange(PObject pObject) {
}

/**
* @return If there are any changes
* @return If there are any changes from objects that were manipulated by user interaction
*/
public boolean isChange() {
Collection<Change> changeValues = changes.values();
Change[] changeArray = changeValues.toArray(new Change[0]);
for (Change change : changeArray) {
if (change.isNew) {
return true;
}
}
return false;
}

/**
* @return If there are any changes that end up in the state manager form user interactions or annotations
* needing to create missing content streams or popups.
*/
public boolean isChanged() {
return !changes.isEmpty();
public boolean isNoChange() {
return changes.isEmpty();
}

/**
Expand All @@ -139,22 +165,11 @@ public int getChangedSize() {
/**
* @return An Iterator&lt;PObject&gt; for all the changes objects, sorted
*/
public Iterator<PObject> iteratorSortedByObjectNumber() {
Collection<PObject> coll = changes.values();
/*
* This code allows me to force an object to be treated as modified,
* so I can debug how we write out that kind of object, before we
* add a ui to actually edit it.
Reference ref = new Reference(10,0);
Object ob = trailer.getLibrary().getObject(ref);
logger.severe("Object 10: " + ob + " ob.class: " + ob.getClass().getName());
java.util.HashSet<PObject> hs = new java.util.HashSet<PObject>(coll);
hs.add(new PObject(ob, ref));
coll = hs;
*/
PObject[] arr = coll.toArray(new PObject[coll.size()]);
public Iterator<Change> iteratorSortedByObjectNumber() {
Collection<Change> coll = changes.values();
Change[] arr = coll.toArray(new Change[0]);
Arrays.sort(arr, new PObjectComparatorByReferenceObjectNumber());
List<PObject> sortedList = Arrays.asList(arr);
List<Change> sortedList = Arrays.asList(arr);
return sortedList.iterator();
}

Expand All @@ -164,16 +179,16 @@ public PTrailer getTrailer() {


private static class PObjectComparatorByReferenceObjectNumber
implements Comparator<PObject> {
public int compare(PObject a, PObject b) {
implements Comparator<Change> {
public int compare(Change a, Change b) {
if (a == null && b == null)
return 0;
else if (a == null)
return -1;
else if (b == null)
return 1;
Reference ar = a.getReference();
Reference br = b.getReference();
Reference ar = a.pObject.getReference();
Reference br = b.pObject.getReference();
if (ar == null && br == null)
return 0;
else if (ar == null)
Expand All @@ -189,5 +204,23 @@ else if (aron > bron)
return 0;
}
}

/**
* Wrapper class of a pObject and how it was created. The newFlag differentiates if the object was created
* by a user action vs the core library creating an object that isn't in the source file but needed for rendering.
*/
public class Change {
protected PObject pObject;
protected boolean isNew;

public Change(PObject pObject, boolean isNew) {
this.pObject = pObject;
this.isNew = isNew;
}

public PObject getPObject() {
return pObject;
}
}
}

Loading

0 comments on commit 919f2b2

Please sign in to comment.