/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ // CPaneEnabler is a more general form of CButtonEnabler, originally written by John R. McMullen. // The generalization was done by Mark Young. // CSlaveEnabler was written by John R. McMullen #include "CPaneEnabler.h" #include "LSharable.h" #include "MPaneEnablerPolicy.h" #include "CTargetedUpdateMenuRegistry.h" #include //====================================== #pragma mark --------- class CPaneMaster //====================================== //====================================== class CPaneMaster //====================================== : public LAttachable // CPaneEnablers all attach to this , public LSharable // shared by all CPaneEnablers. { public: CPaneMaster(); virtual ~CPaneMaster(); static CPaneMaster* sPaneMaster; }; // class CPaneMaster CPaneMaster* CPaneMaster::sPaneMaster = nil; //----------------------------------- CPaneMaster::CPaneMaster() //----------------------------------- { sPaneMaster = this; } // CPaneMaster::CPaneMaster() //----------------------------------- CPaneMaster::~CPaneMaster() //----------------------------------- { sPaneMaster = nil; } // CPaneMaster::~CPaneMaster() //====================================== #pragma mark --------- class CPaneEnabler //====================================== //----------------------------------- CPaneEnabler::CPaneEnabler( ) //----------------------------------- : LAttachment() , mPane(nil) { CommonInit(); } // CPaneEnabler::CPaneEnabler //----------------------------------- CPaneEnabler::CPaneEnabler(LStream* inStream) //----------------------------------- : LAttachment(inStream) , mPane(nil) { CommonInit(); } // CPaneEnabler::CPaneEnabler void CPaneEnabler :: CommonInit ( ) { SetMessage(msg_Event); // execute me only for event messages. LAttachable *host = LAttachable::GetDefaultAttachable(); mPane = dynamic_cast(host); Assert_(mPane); try { if (!CPaneMaster::sPaneMaster) new CPaneMaster; CPaneMaster::sPaneMaster->AddUser(this); CPaneMaster::sPaneMaster->AddAttachment(this, nil, false); // don't care where, master is not owner. } catch (...) { } LAttachable::SetDefaultAttachable(host); // Restore, because LAttachable's constructor (called when we made // the new pane master) clobbers the default attachable } // CommonInit //----------------------------------- CPaneEnabler::~CPaneEnabler() //----------------------------------- { if (CPaneMaster::sPaneMaster) { CPaneMaster::sPaneMaster->RemoveAttachment(this); CPaneMaster::sPaneMaster->RemoveUser(this); } } // CPaneEnabler::~CPaneEnabler //----------------------------------- void CPaneEnabler::UpdatePanes() //----------------------------------- { if (CPaneMaster::sPaneMaster) CPaneMaster::sPaneMaster->ExecuteAttachments(msg_Event, nil); } // CPaneEnabler::UpdatePanes //----------------------------------- void CPaneEnabler::ExecuteSelf(MessageT /* inMessage */, void*) //----------------------------------- { MPaneEnablerPolicy* thePolicy = dynamic_cast(mPane); LPane* thePane = dynamic_cast(mPane); LControl* theControl = dynamic_cast(mPane); if (thePolicy) { // Delegate the policy thePolicy->HandleEnablingPolicy(); } else if (theControl) { // Default enabling policy for LControl LCommander* theTarget = LCommander::GetTarget(); MessageT command = theControl->GetValueMessage(); Boolean enabled = false; Boolean usesMark = false; Str255 outName; Char16 outMark; if (!CTargetedUpdateMenuRegistry::UseRegistryToUpdateMenus() || CTargetedUpdateMenuRegistry::CommandInRegistry(command)) { if (!mPane->IsActive() || !mPane->IsVisible()) return; if (!theTarget) return; theTarget->ProcessCommandStatus(command, enabled, usesMark, outMark, outName); if (enabled) mPane->Enable(); else mPane->Disable(); } } else if (thePane) { // Default enabling policy for LPane mPane->Enable(); } else throw; } // CPaneEnabler::ExecuteSelf //====================================== #pragma mark --------- class CSlaveEnabler //====================================== //----------------------------------- CSlaveEnabler::CSlaveEnabler(LStream* inStream) //----------------------------------- : LAttachment(inStream) , mControllingControl(nil) , mControllingID(0) , mPane(nil) { *inStream >> mControllingID; LAttachable *host = LAttachable::GetDefaultAttachable(); mPane = dynamic_cast(host); Assert_(mPane); SetMessage(msg_DrawOrPrint); } // CSlaveEnabler::CSlaveEnabler //----------------------------------- void CSlaveEnabler::Update(SInt32 inValue) //----------------------------------- { if (inValue != 0) mPane->Enable(); else mPane->Disable(); } // CSlaveEnabler::Update //----------------------------------- void CSlaveEnabler::ExecuteSelf(MessageT inMessage, void*) // When our pane is to be drawn for the first time, find our controlling control // and set the enabling accordingly. Then turn off attachment messages. //----------------------------------- { if (inMessage == msg_DrawOrPrint && !mControllingControl) { mControllingControl = dynamic_cast( mPane->GetSuperView()->FindPaneByID(mControllingID)); Assert_(mControllingControl); if (mControllingControl) { mControllingControl->AddListener(this); if (mControllingControl->GetValueMessage() == 0) mControllingControl->SetValueMessage(msg_Click); Update(mControllingControl->GetValue()); } SetMessage(msg_Nothing); // don't call me again } } // CSlaveEnabler::ExecuteSelf //----------------------------------- void CSlaveEnabler::ListenToMessage(MessageT inMessage, void* ioParam) // Listening to our controlling control for when it does a value broadcast //----------------------------------- { if (mControllingControl && inMessage == mControllingControl->GetValueMessage()) Update(*(Int32*)ioParam); } // CSlaveEnabler::ListenToMessage