Sorting Pages in QuarkXPress: A Constrained Approach

Click For Summary

Discussion Overview

The discussion revolves around a sorting problem in QuarkXPress, specifically how to efficiently reorder pages using only the provided functions for inserting pages before or after others. Participants explore the constraints of the Quark environment and the implications of page renumbering on the sorting process.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant describes the challenge of sorting pages in QuarkXPress without direct access to the internal data structure, relying solely on insert functions.
  • Another participant suggests that without a delete function accompanying each insert, pages could become duplicated, proposing a "swap" function as a potential solution.
  • A participant questions the necessity of optimizing the sorting routine, pondering whether it consumes significant resources or is merely an intellectual exercise.
  • Some participants mention sorting algorithms like quicksort and mergesort, noting their predictable movement of pages and potential efficiency in the context of the problem.
  • Concerns are raised about the implications of removing pages from the document, highlighting the complexity of maintaining links and resources associated with pages.
  • A participant reflects on their own confusion stemming from using Quark's "renumber page" function, suggesting that separating the sorting and renumbering processes may yield better results.
  • Details of a sorting method implemented in code are shared, illustrating the challenges faced when trying to sort and renumber pages concurrently.

Areas of Agreement / Disagreement

Participants express differing views on the necessity and efficiency of the sorting process, with some questioning its importance while others emphasize the need for a functional solution. The discussion remains unresolved regarding the optimal approach to sorting and renumbering pages.

Contextual Notes

Limitations include the lack of access to Quark's internal data structure, the potential for page duplication without a delete function, and the complexity introduced by page links and resources. The sorting algorithm's effectiveness is also contingent on the interaction with Quark's functions.

ktoz
Messages
170
Reaction score
12
Hi

I have a sorting problem I haven't been able to solve and was hoping someone here could lend some insights.

The basic problem is resorting pages in a page layout application (QuarkXPress) where I'm constrained to only the functions Quark supplies for moving pages around in a document. Basically all I can do is place a page before or after another page. I have no access to the internal data structure so can't just grab the page array and swap pointers.

The difficulty arises when I perform an insert before/after a page, the indexes for everything after the insert changes which requires recomputing the entire array (at least in my very inefficient efforts thus far) and I'd like to come up with something a bit more elegant.

Here is the problem space

- Quark native page array with no access to it's elements or structure. The only known about this array is that pages are accessed by one based index using an accessor function.
- An unordered associative array (an Object-C http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/Reference/Reference.html") where array keys are the unique page id stored in a database. The database and NSDictionary are mine and are not part of Quark. I use them to provide direct access to a page without having to search the entire array in a loop.
- The only Quark manipulation functions available are insert before/insert after.
- I would like any solution to use only one of the insert before/insert after functions so as to keep it simple and automatic.

With those in mind, here is a concrete example:

Say there is an array of 4 pages (1 thru 4) sorted correctly and the user renumbers page 2 to page 10

Code:
initial page sort: 
[1, 2, 3, 4]

initial associative array (NSDictionary) : 
{ 
	754: {
			id: 754, 
			number: 1,
			ads: {}, 
			images: {}, 
			stories: {}
		}, 
	755: {
			id: 755, 
			number: 2,
			ads: {}, 
			images: {}, 
			stories: {}
		}, 
	756: {
			id: 756, 
			number: 3,
			ads: {}, 
			images: {}, 
			stories: {}
		}, 
	757: {
			id: 757, 
			number: 4,
			ads: {}, 
			images: {}, 
			stories: {}
		}
}

User renumbers page 2
Code:
Quark order before resort: [1, 10, 3, 4]
NSDictionary after renumbering: 
{ 
	754: {
			id: 754, 
			number: 1,
			ads: {}, 
			images: {}, 
			stories: {}
		}, 
	755: {
			id: 755, 
			number: 10,
			ads: {}, 
			images: {}, 
			stories: {}
		}, 
	756: {
			id: 756, 
			number: 3,
			ads: {}, 
			images: {}, 
			stories: {}
		}, 
	757: {
			id: 757, 
			number: 4,
			ads: {}, 
			images: {}, 
			stories: {}
		}
}

Sorted key array:
[754, 756, 757, 755]

Since the NSDictionary is mine, I'm free to do key sorts using standard sorting functions and can use this array as reference for sorting the Quark pages. Keep in mind that the actual NSDictionary itself is not resorted though. I can create arrays of sorted keys, but for efficiency sake, the dictionary preserves it's initial order.

Now using only "insert before" or "insert after" (but not both) resort the page array to match the order found in the key array.

This may actually be relatively easy but I've developed a brain block and haven't been able to figure it out. Any help greatly appreciated
 
Last edited by a moderator:
Technology news on Phys.org
I'm confused, somewhere in the process it would seem you'd need a delete for every insert, else the pages would just get duplicated. Given this, you could then implement a "swap" function, to swap two pages in the array, which would only affect the indexes during each swap operation.
 
The first and most important question -- does this even matter? Does this sorting routine actually consume so many resources that it deserves to be optimized? (or alternatively, is this exercise intended for entertainment value?)


Anyways, I note that a quicksort moves pages around in a very predictable fashion -- you shouldn't have to recompute anything: any time you come to a page, you should just know how far it's moved from its original location. Mergesort may also share this quality.

Or, think outside the box: can you remove pages from the document? Maybe you can put them into your own handcrafted page array, and then put them back into the document. If you can't do this directly, can you move a page from one document into another? Then you could create new documents to serve that purpose.
 
Hurkyl said:
The first and most important question -- does this even matter? Does this sorting routine actually consume so many resources that it deserves to be optimized? (or alternatively, is this exercise intended for entertainment value?)

It's not an exercise. I need this for a real Quark plugin. The actual sort probably doesn't consume many resources, it's just that all my efforts have produced really strange results, pages sorted in ways that are hard to unravel.

Anyways, I note that a quicksort moves pages around in a very predictable fashion -- you shouldn't have to recompute anything: any time you come to a page, you should just know how far it's moved from its original location. Mergesort may also share this quality.

But I don't know. Quark seems to maintain it's own internal indexing list and any time you swap two pages, this internal list gets invalidated and you have to start at the beginning and reset all the indexes for each page. I may have this wrong, but as I said, I have a brain block on this one...

Or, think outside the box: can you remove pages from the document? Maybe you can put them into your own handcrafted page array, and then put them back into the document. If you can't do this directly, can you move a page from one document into another? Then you could create new documents to serve that purpose.

Not realistic. Pages can have links to other pages (Think of a newspaper where a story can jump to another page) so removing a page requires unlinking one or several stories, remembering which box on which page it jumped to and relinking etc. Not to mention that there are lots of large resources on a page (photos, graphics, ads) that can make copying the entire page very resource intensive.

As so often happens, the act of clarifying the problem for a post, has helped me see where the algorithm is messing up. It comes from using Quark's "renumber page" function. If I don't renumber the page, the following algorithm works perfectly

Code:
The actual Quark function is under NDA so here's an a fake function witrh the same arguments

QuarkNDAMovePageFunction(layoutRefNum, moveStartIndex, moveEndIndex, destIndex, insertOption);

Here's my XTLayoutView class's sort method

- (void) sortPageViews
{
	int		layoutRefNum	= [self qxLayoutRef],
			maxIndex	= [pageViews count] - 1, // pageViews is my internal list of which pages a document contains
			swapCount	= 1,
			i;
						
	XTPageView	*pg1,
			*pg2;
						
	
	while (swapCount > 0)
	{
		swapCount	= 0;
		
		for (i = 0; i < maxIndex; i++)
		{
			// page indexes in array are i, i + 1 (zero based)
			pg1	= [pageViews objectAtIndex: i];
			pg2	= [pageViews objectAtIndex: i + 1];
			
			NSLog(@"comparing %hi with: %hi", [pg1 pageNumber], [pg2 pageNumber]);
			
			if ([pg1 pageNumber] > [pg2 pageNumber])
			{
				NSLog(@"swapping: %hi", [pg1 pageNumber], [pg2 pageNumber]);
				
				// move the pg1 to it's new location
				// page indexes in document are i + 1, i + 2 (1 based)
				QuarkNDAMovePageFunction(layoutRefNum, i + 1, i + 1, i + 2, INSERT_AFTER);
				
				// update the qxPageRefs (index) for both pages
				[pg1 setQXPageRef: i + 2];
				[pg2 setQXPageRef: i + 1];
				
				// swap elements in array
				[pageViews swapObject: pg1 withObject: pg2];
				
				// increment swapcount
				swapCount++;
			}
		}
	}
}

I think if I sort the pages and then make another pass renumbering them, it will be all better. I was just trying to make the renumbering concurrent with the sort and this was what got me so confused.
 

Similar threads

  • · Replies 13 ·
Replies
13
Views
3K
Replies
20
Views
2K
  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 7 ·
Replies
7
Views
3K
  • · Replies 10 ·
Replies
10
Views
3K
  • · Replies 4 ·
Replies
4
Views
2K
  • · Replies 3 ·
Replies
3
Views
8K
  • · Replies 1 ·
Replies
1
Views
4K
  • · Replies 5 ·
Replies
5
Views
4K