// $Revision: 1.36 $ // ViewerViews.C // Copyright (C) 1994, 1995 Taligent, Inc. All rights reserved. #ifndef TaligentSamples_VIEWERVIEWS #include "ViewerViews.h" #endif #ifndef TaligentSamples_STOCKGRAPHCONSTRUCTOR #include "StockGraphConstructor.h" #endif #ifndef TaligentSamples_VIEWERDRAWERS #include "ViewerDrawers.h" #endif #ifndef TaligentSamples_VIEWERPRESENTERSTATE #include "ViewerPresenterState.h" #endif #ifndef TaligentSamples_STOCKDATA #include #endif #ifndef TaligentSamples_STANDARDGRAPH #include #endif #ifndef TaligentSamples_ATOMICMODEL #include #endif #ifndef Taligent_SCROLLINGVIEW #include #endif #ifndef Taligent_TEXTDISPLAY #include #endif //============================================================================== // TViewerContentView TaligentTypeExtensionMacro(TViewerContentView); TViewerContentView::TViewerContentView() : TDOMDocumentComponentView(), fConnection(), fBackgroundPaint(NIL), fScrollingView(NIL), fGraphView(NIL), fWaitingForNotification(false), fNameDisplay(), fNameArea() { } TViewerContentView::TViewerContentView( TGUIBundle* guiBundleToAlias, const TPaint& backgroundPaint) : TDOMDocumentComponentView(guiBundleToAlias), fConnection(), fBackgroundPaint(NIL), fScrollingView(NIL), fGraphView(NIL), fWaitingForNotification(false), fNameDisplay(), fNameArea() { const TColor& backgroundColor = *backgroundPaint.GetColor(); fScrollingView = new TScrollingView(TScrollingView::kBothScrollbars); fScrollingView->AdoptClipBackgroundBundle(new TGrafBundle(backgroundColor, backgroundColor)); AdoptChild(fScrollingView); fBackgroundPaint = ::Copy(backgroundPaint); } TViewerContentView::~TViewerContentView() { } TStream& TViewerContentView::operator>>=(TStream& toStream) const { // fWaitingForNotification and fNameArea are transient data that // need not be streamed. ::WriteVersion(toStream, kOriginalVersion); TDOMDocumentComponentView::operator>>=(toStream); ::Flatten(fScrollingView, toStream); ::Flatten(fGraphView, toStream); ::Flatten(fBackgroundPaint.GetObject(), toStream); fNameDisplay >>= toStream; return toStream; } TStream& TViewerContentView::operator<<=(TStream& fromStream) { // fWaitingForNotification and fNameArea are transient data that // need not be streamed. ::ReadVersion(fromStream, kOriginalVersion, kOriginalVersion); TDOMDocumentComponentView::operator<<=(fromStream); ::Resurrect(fScrollingView, fromStream); ::Resurrect(fGraphView, fromStream); TPaint* backgroundPaint = NIL; ::Resurrect(backgroundPaint, fromStream); fBackgroundPaint = backgroundPaint; fNameDisplay <<= fromStream; return fromStream; } TModelSelection* TViewerContentView::CreateSelectionFromPoint(const TGPoint& where) const { // This override of CreateSelectionFromPoint is obsolete. See the // Taligent Selection Tool sample program. return TDOMDocumentComponentView::CreateSelectionFromPoint(where); } void TViewerContentView::AdoptGraphView(TGraphView* contentView) { ::Assertion(contentView != NIL, "Can't adopt NIL graph view."); ::Assertion(fScrollingView != NIL, "Scrolling view must not be NIL."); fScrollingView->AdoptViewToScroll(contentView); fGraphView = contentView; fConnection.AddInterest( fGraphView->GetReadyInterest(), &TViewerContentView::HandleGraphViewReady); } void TViewerContentView::DrawContents(TGrafPort& port) const { // Paint the background const TColor& backgroundColor = *fBackgroundPaint->GetColor(); TArea(fNameArea, new TGrafBundle(backgroundColor, TAttributeState::kFillAndFrame)).Draw(port); // If everything's cool, draw the stock name, selection and // drop feedback. Otherwise, show our current status. if (!fWaitingForNotification) { fNameDisplay.Draw(port); TDOMDocumentComponentView::DrawContents(port); } else { TStandardText waitText; GetWaitingText(waitText); TTextDisplay statusDisplay(fNameDisplay); statusDisplay.SetText(waitText); statusDisplay.Draw(port); } } void TViewerContentView::HandleAfterConnectionToViewRoot() { TDOMDocumentComponentView::HandleAfterConnectionToViewRoot(); { // Scope this part because later on Update tries to get a write entry // to the document component and if we don't let go of the ready entry, // the thread will lock up. TDocumentComponentReadEntry entry(GetModelReference()); const TAtomicModelOn* model = TAtomicModelOn::LookupForReading(GetModelReference()); fConnection.AddInterest( model->GetSelectedContentsReplacedInterest(), &TViewerContentView::HandleModelOrPresenterStateChanged); const TViewerPresenterState* presenterState = TViewerPresenterState::LookupForReading(GetPresenterStateReference()); fConnection.AddInterest( presenterState->GetNewGraphConstructorInterest(), &TViewerContentView::HandleModelOrPresenterStateChanged); } fConnection.SetReceiver(this); fConnection.SetRequestProcessor(GetRequestProcessor()); fConnection.Connect(); fWaitingForNotification = true; Update(); fNameDisplay.SetPointSize(GetTextSize()); GCoordinate nameCenterY = GetNameAreaHeight() / 2.0; TGRect nameBounds(fNameDisplay.GetTextBounds()); TGPoint nameOrigin; fNameDisplay.GetOrigin(nameOrigin); fNameDisplay.SetOrigin(TGPoint(GetExtraSpace(), nameCenterY + (nameBounds.GetHeight() / 2.0) - (nameBounds.GetBottomRight() - nameOrigin).fY)); } void TViewerContentView::HandleBeforeDisconnectionFromViewRoot() { fConnection.Disconnect(); fConnection.RemoveAllInterests(); TDOMDocumentComponentView::HandleBeforeDisconnectionFromViewRoot(); } void TViewerContentView::HandleCurrentSelectionChanged(const TNotification& note) { // The inherited HandleCurrentSelectionChanged function calls // InvalidateAll. This view only needs to invalidate itself, not // its children. Invalidate(fNameArea); } void TViewerContentView::HandleAllocatedAreaChanged(const TGArea& newArea) { TDOMDocumentComponentView::HandleAllocatedAreaChanged(newArea); TGRect bounds(newArea.GetBounds()); bounds.fTop = GetNameAreaHeight(); fScrollingView->SetAllocatedAreaInParent(bounds); // Determine the area which will be invalidated during drag and // drop interactions. Make sure it does not intersect the bounds of // the scrolling view. fNameArea = newArea - bounds; } void TViewerContentView::HandleModelOrPresenterStateChanged(const TNotification& notification) { fWaitingForNotification = true; Draw(*GetGrafPort()); Update(); } void TViewerContentView::HandleGraphViewReady(const TNotification& notification) { fWaitingForNotification = false; Invalidate(); } void TViewerContentView::Update() { try { TDocumentComponentWriteEntry entry(GetPresenterStateReference()); TViewerPresenterState* presenterState = TViewerPresenterState::LookupForWriting(GetPresenterStateReference()); TStockGraphConstructor* graphConstructor = presenterState->GetGraphConstructor(); const TAtomicModelOn* model = TAtomicModelOn::LookupForReading(GetModelReference()); const TStockData* stock = model->GetValueForReading(); if (graphConstructor != NIL && fGraphView != NIL) { fGraphView->ReconstructGraph(*graphConstructor, *stock); } fNameDisplay.SetText(stock->GetName()); } catch (const TCompoundDocumentException& exception) { } } GCoordinate TViewerContentView::GetNameAreaHeight() const { return GetTextSize() + (2 * GetExtraSpace()); } GCoordinate TViewerContentView::GetTextSize() const { return 24.0; } GCoordinate TViewerContentView::GetExtraSpace() const { return 10.0; } void TViewerContentView::GetWaitingText(TStandardText& waitText) const { waitText.Delete(); waitText.Insert("Please wait ..."); } TViewerContentView::TViewerContentView(const TViewerContentView& src) : TDOMDocumentComponentView(), fBackgroundPaint(NIL), fScrollingView(NIL), fWaitingForNotification(false), fNameDisplay(), fNameArea() { ::Assertion(false, "Can't copy TViewerContentView."); } TViewerContentView& TViewerContentView::operator=(const TViewerContentView& src) { ::Assertion(false, "Can't call TViewerContentView assignment operator."); return *this; } //============================================================================== // TGraphView TaligentTypeExtensionMacro(TGraphView); TGraphView::TGraphView() : TSimpleView(), fBackgroundPaint(NIL), fImage(NIL), fGraph(NIL) { } TGraphView::TGraphView( TStandardGraph* adoptedGraph, const TPaint& backgroundPaint) : TSimpleView(), fBackgroundPaint(NIL), fImage(NIL), fGraph(adoptedGraph) { ::Assertion(fGraph != NIL, "Graph must be non-NIL"); fBackgroundPaint = ::Copy(backgroundPaint); } TGraphView::~TGraphView() { } TStream& TGraphView::operator>>=(TStream& toStream) const { ::WriteVersion(toStream, kOriginalVersion); TSimpleView::operator>>=(toStream); ::Flatten(fBackgroundPaint.GetObject(), toStream); ::Flatten(fGraph.GetObject(), toStream); return toStream; } TStream& TGraphView::operator<<=(TStream& fromStream) { ::ReadVersion(fromStream, kOriginalVersion, kOriginalVersion); TSimpleView::operator<<=(fromStream); TPaint* backgroundPaint; ::Resurrect(backgroundPaint, fromStream); fBackgroundPaint = backgroundPaint; TStandardGraph* graph; ::Resurrect(graph, fromStream); fGraph = graph; return fromStream; } void TGraphView::ReconstructGraph( TStockGraphConstructor& constructor, const TStockData& stock) { ::Assertion(fGraph != NIL, "Graph must be non-NIL"); try { const TColor& backgroundColor = *fBackgroundPaint->GetColor(); constructor.Do(*fGraph, stock); TGRect graphBounds(fGraph->GetGeometricBounds()); TGPoint graphSize(graphBounds.GetSize()); TDeleterFor image = new TIndexedImage(TGPoint::kOrigin, graphSize); TGrafPort& imagePort = *image->GetGrafPort(); TArea(image->GetGeometricBounds(), new TGrafBundle(backgroundColor, backgroundColor)).Draw(imagePort); fGraph->TranslateBy(TGPoint(-graphBounds.fLeft,-graphBounds.fTop)); fGraph->Draw(imagePort); fImage = image.OrphanObject(); SetAllocatedArea(TGRect(TGPoint::kOrigin, graphSize)); } catch (const TStockException& exception) { // Use a NIL image as an indication that something bad happened. fImage = NIL; } if (fImage == NIL) { TStandardText errorMessage; GetErrorMessage(errorMessage); TTextDisplay temporaryMessage(errorMessage); SetAllocatedArea(TGRect(TGPoint::kOrigin, temporaryMessage.GetTextBounds().GetSize())); } Notify(TNotification(GetReadyInterest())); } TInterest TGraphView::GetReadyInterest() const { return TInterest((TGraphView*)this, TToken("TGraphView::kReady")); } void TGraphView::DrawContents(TGrafPort& port) const { TGArea viewGArea; GetAllocatedArea(viewGArea); if (fImage != NIL) { viewGArea.Subtract(fImage->GetGeometricBounds()); } const TColor& backgroundColor = *fBackgroundPaint->GetColor(); TArea viewArea(viewGArea, new TGrafBundle(backgroundColor, backgroundColor)); viewArea.Draw(port); if (fImage != NIL) { fImage->Draw(port); } else { TStandardText errorMessage; GetErrorMessage(errorMessage); TTextDisplay error(errorMessage); error.SetOrigin(-error.GetTextBounds().GetTopLeft()); error.Draw(port); } } void TGraphView::GetErrorMessage(TStandardText& fillThisIn) const { fillThisIn.Delete(); fillThisIn.Insert("Stock data is unavailable."); } TGraphView::TGraphView(const TGraphView& source) : TSimpleView(), fBackgroundPaint(NIL), fImage(NIL), fGraph(NIL) { ::Assertion(false, "Can't copy TGraphView."); } TGraphView& TGraphView::operator=(const TGraphView& source) { ::Assertion(false, "Can't call TGraphView assignment operator."); return *this; }