4#include "Stroika/Frameworks/StroikaPreComp.h" 
   13#include "StandardStyledTextImager.h" 
   15#include "HiddenText.h" 
   20using namespace Stroika::Frameworks;
 
   21using namespace Stroika::Frameworks::Led;
 
   28HidableTextMarkerOwner::HidableTextMarkerOwner (TextStore& textStore)
 
   29    : fTextStore{textStore}
 
   31    SetInternalizer (
nullptr); 
 
   32    SetExternalizer (
nullptr); 
 
   33    fTextStore.AddMarkerOwner (
this);
 
   36HidableTextMarkerOwner::~HidableTextMarkerOwner ()
 
   38    Require (fMarkersToBeDeleted.IsEmpty ());
 
   40        MarkerList markers = CollectAllInRange (0, fTextStore.GetLength () + 1);
 
   41        if (not markers.empty ()) {
 
   44                copy (markers.begin (), markers.end (), inserter (tmp, tmp.begin ()));
 
   45                GetTextStore ().RemoveMarkers (Traversal::Iterator2Pointer (tmp.begin ()), tmp.size ());
 
   47            for (
auto i = markers.begin (); i != markers.end (); ++i) {
 
   51        fTextStore.RemoveMarkerOwner (
this);
 
   66void HidableTextMarkerOwner::HideAll ()
 
   68    HideAll (0, fTextStore.GetEnd () + 1);
 
   71void HidableTextMarkerOwner::HideAll (
size_t from, 
size_t to)
 
   74    MarkerList markers = CollectAllInRange (from, to);
 
   75    sort (markers.begin (), markers.end (), LessThan<HidableTextMarker> ());
 
   77    for (
auto i = markers.rbegin (); i != markers.rend (); ++i) {
 
   78        if (TextStore::Overlap (**i, from, to)) {
 
   92void HidableTextMarkerOwner::ShowAll ()
 
   94    ShowAll (0, fTextStore.GetEnd () + 1);
 
   97void HidableTextMarkerOwner::ShowAll (
size_t from, 
size_t to)
 
  100    MarkerList markers = CollectAllInRange (from, to);
 
  101    sort (markers.begin (), markers.end (), LessThan<HidableTextMarker> ());
 
  103    for (
auto i = markers.rbegin (); i != markers.rend (); ++i) {
 
  104        if (TextStore::Overlap (**i, from, to)) {
 
  105#if qStroika_Foundation_Debug_AssertionsChecked 
  106            HidableTextMarkerOwner::Invariant_ (); 
 
  109#if qStroika_Foundation_Debug_AssertionsChecked 
  110            HidableTextMarkerOwner::Invariant_ (); 
 
  128void HidableTextMarkerOwner::MakeRegionHidable (
size_t from, 
size_t to)
 
  130    Require (from <= to);
 
  137    MarkerList hidableTextMarkersInRange = CollectAllInRange (from, to);
 
  140    if (hidableTextMarkersInRange.size () == 1 and hidableTextMarkersInRange[0]->GetStart () <= from and hidableTextMarkersInRange[0]->GetEnd () >= to) {
 
  144    sort (hidableTextMarkersInRange.begin (), hidableTextMarkersInRange.end (), LessThan<HidableTextMarker> ());
 
  146    HidableTextMarker* prevNonEmptyMarker = 
nullptr; 
 
  149        MarkerList tmp = CollectAllInRange (from - 1, from);
 
  151        for (
auto i = tmp.begin (); i != tmp.end (); ++i) {
 
  152            if ((*i)->IsShown () and (*i)->GetEnd () == from) {
 
  153                prevNonEmptyMarker = *i;
 
  161        TextStore::SimpleUpdater updater{fTextStore, from, to};
 
  164        for (
auto i = hidableTextMarkersInRange.begin (); i != hidableTextMarkersInRange.end (); ++i) {
 
  166            if (prevNonEmptyMarker == 
nullptr) {
 
  167                Assert (i == hidableTextMarkersInRange.begin ()); 
 
  168                prevNonEmptyMarker = *i;
 
  170                DISABLE_COMPILER_MSC_WARNING_START (6011)
 
  171                if (from < prevNonEmptyMarker->GetStart ()) {
 
  172                    if (prevNonEmptyMarker->IsShown ()) {
 
  173                        fTextStore.SetMarkerStart (prevNonEmptyMarker, from);
 
  177                        Assert (prevNonEmptyMarker->GetStart () > from);
 
  178                        GetTextStore ().AddMarker (MakeHidableTextMarker (), from, prevNonEmptyMarker->GetStart () - from, 
this);
 
  181                DISABLE_COMPILER_MSC_WARNING_END (6011)
 
  183            else if (prevNonEmptyMarker->IsShown ()) {
 
  185                fMarkersToBeDeleted.AccumulateMarkerForDeletion (*i);
 
  188        if (prevNonEmptyMarker == 
nullptr) {
 
  189            GetTextStore ().AddMarker (MakeHidableTextMarker (), from, to - from, 
this);
 
  192            if (prevNonEmptyMarker->GetEnd () < to) {
 
  193                if (prevNonEmptyMarker->IsShown ()) {
 
  194                    fTextStore.SetMarkerEnd (prevNonEmptyMarker, to);
 
  198                    Assert (to > prevNonEmptyMarker->GetEnd ());
 
  199                    GetTextStore ().AddMarker (MakeHidableTextMarker (), prevNonEmptyMarker->GetEnd (), to - prevNonEmptyMarker->GetEnd (), 
this);
 
  214void HidableTextMarkerOwner::MakeRegionUnHidable (
size_t from, 
size_t to)
 
  216    Require (from <= to);
 
  223    MarkerList hidableTextMarkersInRange = CollectAllInRange (from, to);
 
  225    if (hidableTextMarkersInRange.empty ()) {
 
  229    TempMarker pastSelMarker (GetTextStore (), to + 1, to + 1);
 
  233        TextStore::SimpleUpdater updater{fTextStore, from, to};
 
  235            sort (hidableTextMarkersInRange.begin (), hidableTextMarkersInRange.end (), LessThan<HidableTextMarker>{});
 
  239            for (
auto i = hidableTextMarkersInRange.begin (); i != hidableTextMarkersInRange.end (); ++i) {
 
  240                if (i == hidableTextMarkersInRange.begin () and (*i)->GetStart () < from) {
 
  243                    size_t oldEnd = (*i)->GetEnd ();
 
  244                    fTextStore.SetMarkerEnd (*i, from);
 
  246                        fTextStore.AddMarker (MakeHidableTextMarker (), to, oldEnd - to, 
this);
 
  249                else if (i + 1 == hidableTextMarkersInRange.end () and (*i)->GetEnd () > to) {
 
  251                    fTextStore.SetMarkerStart (*i, to);
 
  254                    fMarkersToBeDeleted.AccumulateMarkerForDeletion (*i);
 
  267        TextStore::SimpleUpdater updater{fTextStore, to, pastSelMarker.GetEnd ()};
 
  283DiscontiguousRun<bool> HidableTextMarkerOwner::GetHidableRegions (
size_t from, 
size_t to)
 const 
  286    DiscontiguousRun<bool> result;
 
  287    MarkerList             markers = CollectAllInRange (from, to);
 
  288    sort (markers.begin (), markers.end (), LessThan<HidableTextMarker> ());
 
  289    size_t relStartFrom = from;
 
  290    for (
auto i = markers.begin (); i != markers.end (); ++i) {
 
  293        (*i)->GetRange (&mStart, &mEnd);
 
  295            mStart = max (mStart, relStartFrom); 
 
  296            mEnd   = min (mEnd, to);             
 
  297            Assert (mStart < mEnd);
 
  298            result.push_back (DiscontiguousRunElement<bool> (mStart - relStartFrom, mEnd - mStart, (*i)->IsShown ()));
 
  305DiscontiguousRun<bool> HidableTextMarkerOwner::GetHidableRegions ()
 const 
  307    return GetHidableRegions (0, fTextStore.GetEnd () + 1);
 
  315bool HidableTextMarkerOwner::GetHidableRegionsContiguous (
size_t from, 
size_t to, 
bool hidden)
 const 
  319    DiscontiguousRun<bool> tmpHack = GetHidableRegions (from, to);
 
  320    if (tmpHack.size () == 1) {
 
  321        return tmpHack[0].fData == hidden and tmpHack[0].fOffsetFromPrev == 0 and tmpHack[0].fElementLength >= to - from;
 
  328            return tmpHack.size () == 0;
 
  338void HidableTextMarkerOwner::SetInternalizer (
const shared_ptr<FlavorPackageInternalizer>& i)
 
  341    if (fInternalizer == 
nullptr) {
 
  342        fInternalizer = make_shared<FlavorPackageInternalizer> (GetTextStore ());
 
  351void HidableTextMarkerOwner::SetExternalizer (
const shared_ptr<FlavorPackageExternalizer>& e)
 
  354    if (fExternalizer == 
nullptr) {
 
  355        fExternalizer = make_shared<FlavorPackageExternalizer> (GetTextStore ());
 
  363void HidableTextMarkerOwner::CollapseMarker (HidableTextMarker* m)
 
  369    m->GetRange (&start, &end);
 
  370    TextStore::SimpleUpdater updater{fTextStore, start, end, 
false};
 
  378void HidableTextMarkerOwner::ReifyMarker (HidableTextMarker* m)
 
  381    Require (not m->fShown);
 
  385        m->GetRange (&start, &end);
 
  387        TextStore::SimpleUpdater updater (fTextStore, start, end, 
false);
 
  399HidableTextMarkerOwner::HidableTextMarker* HidableTextMarkerOwner::MakeHidableTextMarker ()
 
  418    return new LightUnderlineHidableTextMarker{};
 
  421TextStore* HidableTextMarkerOwner::PeekAtTextStore ()
 const 
  426void HidableTextMarkerOwner::AboutToUpdateText (
const UpdateInfo& updateInfo)
 
  429    Assert (fMarkersToBeDeleted.IsEmpty ());
 
  430    inherited::AboutToUpdateText (updateInfo);
 
  433void HidableTextMarkerOwner::DidUpdateText (
const UpdateInfo& updateInfo) 
noexcept 
  435    inherited::DidUpdateText (updateInfo);
 
  436    if (updateInfo.fTextModified) {
 
  438        MarkerList markers = CollectAllInRange_OrSurroundings (updateInfo.fReplaceFrom, updateInfo.GetResultingRHS ());
 
  439        for (
auto i = markers.begin (); i != markers.end (); ++i) {
 
  440            HidableTextMarker* m = *i;
 
  441            if (m->GetLength () == 0) {
 
  442                fMarkersToBeDeleted.AccumulateMarkerForDeletion (m);
 
  446    fMarkersToBeDeleted.FinalizeMarkerDeletions ();
 
  450HidableTextMarkerOwner::MarkerList HidableTextMarkerOwner::CollectAllInRange (
size_t from, 
size_t to)
 const 
  452    MarkersOfATypeMarkerSink2Vector<HidableTextMarker> result;
 
  453    fTextStore.CollectAllMarkersInRangeInto (from, to, 
this, result);
 
  454    return result.fResult;
 
  457HidableTextMarkerOwner::MarkerList HidableTextMarkerOwner::CollectAllInRange_OrSurroundings (
size_t from, 
size_t to)
 const 
  459    MarkersOfATypeMarkerSink2Vector<HidableTextMarker> result;
 
  460    fTextStore.CollectAllMarkersInRangeInto_OrSurroundings (from, to, 
this, result);
 
  461    return result.fResult;
 
  464#if qStroika_Foundation_Debug_AssertionsChecked 
  465void HidableTextMarkerOwner::Invariant_ ()
 const 
  467    MarkerList markers = CollectAllInRange (0, fTextStore.GetEnd () + 1);
 
  469    sort (markers.begin (), markers.end (), LessThan<HidableTextMarker> ());
 
  476    for (
size_t i = 0; i < markers.size (); i++) {
 
  477        HidableTextMarker* m = markers[i];
 
  478        Assert (m->GetLength () > 0);
 
  479        Assert (m->GetStart () >= lastEnd);
 
  480        lastEnd = m->GetEnd ();
 
  482    Assert (lastEnd <= fTextStore.GetLength () + 1);
 
  491HidableTextMarkerOwner::LightUnderlineHidableTextMarker::LightUnderlineHidableTextMarker (
const IncrementalFontSpecification& fsp)
 
  493    fFontSpecification = fsp;
 
  496Color HidableTextMarkerOwner::LightUnderlineHidableTextMarker::GetUnderlineBaseColor ()
 const 
  498    if (fFontSpecification.GetTextColor_Valid ()) {
 
  499        return fFontSpecification.GetTextColor ();
 
  502        return inherited::GetUnderlineBaseColor ();
 
  511UniformHidableTextMarkerOwner::UniformHidableTextMarkerOwner (TextStore& textStore)
 
  512    : inherited{textStore}
 
  516void UniformHidableTextMarkerOwner::HideAll ()
 
  519        inherited::HideAll ();
 
  524void UniformHidableTextMarkerOwner::ShowAll ()
 
  527        inherited::ShowAll ();
 
  532void UniformHidableTextMarkerOwner::MakeRegionHidable (
size_t from, 
size_t to)
 
  534    Require (from <= to);
 
  537    inherited::MakeRegionHidable (from, to);
 
  539        inherited::HideAll ();
 
  542        inherited::ShowAll ();
 
  546#if qStroika_Frameworks_Led_SupportGDI 
  552FontSpecification HidableTextMarkerOwner::FontSpecHidableTextMarker::MakeFontSpec (
const StyledTextImager* , 
const StyleRunElement& runElement)
 const 
  555    for (
auto i = runElement.fSupercededMarkers.begin (); i != runElement.fSupercededMarkers.end (); ++i) {
 
  556        if (StandardStyleMarker* m = 
dynamic_cast<StandardStyleMarker*
> (*i)) {
 
  557            fsp.MergeIn (m->fFontSpecification);
 
  560    fsp.MergeIn (fFontSpecification); 
 
  570void ColoredUniformHidableTextMarkerOwner::FixupSubMarkers ()
 
  573    MarkerList markers = CollectAllInRange_OrSurroundings (0, GetTextStore ().GetEnd () + 1);
 
  574    for (
auto i = markers.begin (); i != markers.end (); ++i) {
 
  575        LightUnderlineHidableTextMarker* m = 
dynamic_cast<LightUnderlineHidableTextMarker*
> (*i);
 
  578            m->fFontSpecification.SetTextColor (fColor);
 
  581            m->fFontSpecification.InvalidateTextColor ();
 
  586ColoredUniformHidableTextMarkerOwner::HidableTextMarker* ColoredUniformHidableTextMarkerOwner::MakeHidableTextMarker ()
 
  588    IncrementalFontSpecification fontSpec;
 
  590        fontSpec.SetTextColor (fColor);
 
  592    return new LightUnderlineHidableTextMarker (fontSpec);
 
#define RequireNotNull(p)