// $Revision: 1.4 $ // Copyright (c) 1994-1995 Taligent, Inc. All rights reserved. #ifndef TaligentSamples_DISJOINTSELECTSTATES #include "DisjointSelectStates.h" #endif // This is just like TSetSelectState, except instead of replacing the original area, // it adds the current selection to it in a disjoint fashion. If both areas are // insertion points, the new area is the tracked insertion point, and if one area // is an insertion point, the new area is the other. TaligentTypeExtensionMacro_Abstract(TDisjointSelectState); TDisjointSelectState::TDisjointSelectState(MTextRepresentation* textRepresentation, TTextChunkIteratorReference& iteratorReference) : TSetSelectState(textRepresentation, iteratorReference) { } TDisjointSelectState::~TDisjointSelectState() { } void TDisjointSelectState::Setup(const TInsertionOffset& initialOffset, const TTextArea& initialArea) { SetOriginalArea(initialArea); TSetSelectState::Setup(initialOffset, initialArea); } // If an area is not an insertion point, it is by definition not empty. void TDisjointSelectState::Track(const TInsertionOffset& trackingOffset, TTextArea& resultArea) { TSetSelectState::Track(trackingOffset, resultArea); if (!fOriginalArea.IsInsertionPoint()) { TTextRegion originalRegion; fOriginalArea.GetRegion(originalRegion); if (resultArea.IsInsertionPoint()) { resultArea = fOriginalArea; } else { TTextRegion resultRegion; resultArea.GetRegion(resultRegion); resultRegion.Add(originalRegion); resultArea.SetRegion(resultRegion); } } } void TDisjointSelectState::SetOriginalArea(const TTextArea& area) { fOriginalArea = area; } // ========================================================================================== // This is like TDisjointSelectState in that it adds the new selection disjointly. It is // like TExtendSelectState in that it extends the selection based on an anchor computed // from it. If the initial area is not disjoint, this behaves exactly like TExtendSelectState. // If it is disjoint, it computes the anchor based on the nearest range, and replaces that // range with one computed from the anchor and the tracking point, setting the selection // to the result. TaligentTypeExtensionMacro_Abstract(TExtendDisjointSelectState); TExtendDisjointSelectState::TExtendDisjointSelectState(MTextRepresentation* textRepresentation, TTextChunkIteratorReference& iteratorReference) : TDisjointSelectState(textRepresentation, iteratorReference) { } TExtendDisjointSelectState::~TExtendDisjointSelectState() { } // Determine both the original area and the anchor for extending. If the inital area is // an insertion point or a contiguous selection, the original area can remain empty; // we will extend as TExtendSelectState. Otherwise, the original area is the initial // area minus the range closest to the initial offset. // // In all cases we determine the range (sometimes of zero length) which is used for the // anchor computation. Like TExtendSelectState, the anchor is the end of that range // furthest from the inital offset. void TExtendDisjointSelectState::Setup(const TInsertionOffset& initialOffset, const TTextArea& initialArea) { TTextRange range; if (initialArea.IsInsertionPoint()) { range.SetBeginAndEnd(initialOffset, initialOffset); } else { TTextRegion region; initialArea.GetRegion(region); if (!region.IsDiscontiguous()) { region.GetBounds(range); } else { TTextOffset closest = TTextOffset::GetMaximum(); TTextRegionIterator iter(region); long offsetLong = initialOffset.GetOffset(); for (const TTextRange* r = iter.First(); r; r = iter.Next()) { long distBegin = abs((long)r->GetBegin() - offsetLong); long distEnd = abs((long)r->GetEnd() - offsetLong); long dist = Min(distBegin, distEnd); if (dist < closest) { closest = dist; range = *r; } } region.Subtract(range); SetOriginalArea(TTextArea(region)); } } TTextOffset lowAnchor = range.GetBegin(); TTextOffset highAnchor = range.GetEnd(); TTextOffset midAnchor = (TTextOffset)(((long)lowAnchor + (long)highAnchor) / 2); TTextOffset offset = initialOffset.GetOffset(); TTextOffset anchor = lowAnchor; if (offset < midAnchor) { anchor = highAnchor; } SetAnchor(TTextArea(TInsertionOffset(anchor, TInsertionOffset::kBeforeOffset))); }