John Levon wrote:

> 
> OK, so we're not calling speller_->close() when the window is closed or
> Close is  pressed - bad, we didn't write out the accepted word list.
> 
> dialogs call controller().stop() but this doesn't actually do anything
> interesting. Angus, how can we make it so that it will call ->close()
> but nothing else will break ? ->close() isn't idempotent for ispell,
> and  it doesn't look like we could safely destruct the speller_
> instance.
> 
> I find this code a little confusing ...  I'm considering a rewrite.

So am I. In fact...

I'd suggest doing nothing to this code for a while. Attached is a NEW Dialog 
class that should make life a LOT easier. I'm pretty sure that this 
abstraction is flexible enough to be used by ALL dialogs and I find it 
coherent. Does it make sense to you too?

We can use this because the Dialogs class (that's frontends/Dialogs not 
frontends/controllers/Dialog) now stores a map<name, dialog> and so can 
access each dialog easily. Moreover, this means that the rather obtuse code 
using signals to hide an inset dialog or update the dialogs on a buffer 
change can now go because we can simply access an individual dialog or loop 
over the container of all dialogs.

Still a work in progress, but it seems to hang together...

Note also that I'm going to move build() back into the xforms/qt/gnome code.

-- 
Angus
// -*- C++ -*-
/**
 * \file Dialog.C
 * This file is part of LyX, the document processor.
 * Licence details can be found in the file COPYING.
 *
 * \author Angus Leeming 
 *
 * Full author contact details are available in file CREDITS
 */

#include "Dialog.h"

#include "ButtonControllerBase.h"
#include "ViewBase.h"



Dialog::Dialog(LyXView & lv)
	: kernel_(lv)
{}


void Dialog::ApplyButton()
{
	apply();
	bc().apply();
}


void Dialog::OKButton()
{
	is_closing_ = true;
	apply();
	is_closing_ = false;
	hide();
	bc().ok();
}


void Dialog::CancelButton()
{
	hide();
	bc().cancel();
}


void Dialog::RestoreButton()
{
	kernel().updateDialog(name_);
	bc().restore();
}


void Dialog::show(string const & data)
{
	if (impl().isBufferDependent() && !kernel().isBufferAvailable())
		return;

	impl().initialiseParams(data);

	bc().readOnly(kernel().isBufferReadonly());
	view().show();

	// The widgets may not be valid, so refresh the button controller
	bc().refresh();
}


void Dialog::update(string const & data)
{
	if (impl().isBufferDependent() && !kernel().isBufferAvailable())
		return;

	impl().initialiseParams(data);

	bc().readOnly(kernel().isBufferReadonly());
	view().update();

	// The widgets may not be valid, so refresh the button controller
	bc().refresh();
}


void Dialog::hide()
{
	impl().clearParams();
	view().hide();
}


void Dialog::apply()
{
	if (kernel().isBufferReadonly())
		return;

	view().apply();
	impl().dispatchParams();

	if (impl().disconnectOnApply() && !is_closing_) {
 		impl().initialiseParams(string());
		view().update();
	}
}


bool Dialog::isVisible() const
{
	return view().isVisible();
}


void Dialog::redraw()
{
	view().redraw();
}


ButtonControllerBase & Dialog::bc() const
{
	lyx::Assert(bc_ptr_.get());
	return *bc_ptr_.get();
}


ViewBase & Dialog::view() const
{
	lyx::Assert(view_ptr_.get());
	return *view_ptr_.get();
}


void Dialog::setView(ViewBase * v)
{
	lyx::Assert(v && !view_ptr_.get());
	view_ptr_.reset(v);
}


void Dialog::setImpl(Impl * i)
{
	lyx::Assert(i && !impl_ptr_.get());
	impl_ptr_.reset(i);
}


void Dialog::setButtonController(ButtonControllerBase * bc)
{
	lyx::Assert(bc && !bc_ptr_.get());
	bc_ptr_.reset(bc);
}


Dialog::Impl::Impl(Dialog & parent)
	: parent_(parent)
{}
// -*- C++ -*-
/**
 * \file Dialog.h
 * This file is part of LyX, the document processor.
 * Licence details can be found in the file COPYING.
 *
 * \author Angus Leeming
 *
 * Full author contact details are available in file CREDITS
 */

#ifndef DIALOG_H
#define DIALOG_H


#include "Kernel.h"
#include "LString.h"
#include <boost/utility.hpp>
#include <boost/scoped_ptr.hpp>


class ButtonControllerBase;
class LyXView;
class ViewBase;


class Dialog : boost::noncopyable {
public:
	///
	Dialog(LyXView &);

	/** These methods are publicly accessible because they are invoked
	    by the View.
	*/
	///
	void ApplyButton();
	///
	void OKButton();
	///
	void CancelButton();
	///
	void RestoreButton();
	    
	/** These methods are publicly accessible because they are invoked
	 *  by the Dialogs class.
	 */
	/** Some dialogs, eg the Tabular or Preferences dialog, can extract
	    the information they require from the kernel. These dialogs will
	    probably be passed an empty string by the calling Dailogs class.
	    The inset dialogs, however, require information specific to
	    an individual inset. This information will be encoded in the
	    string and must be translated into a set of parameters that
	    can be updated from the dialog.
	 */
	void show(string const & data = string());
	///
	void update(string const & data = string());
	///
	void hide();
	///
	bool isVisible() const;
	/// (Eg, the GUI colours have been changed.)
	void redraw();

	/** When Applying it's useful to know whether the dialog is about
	 *  to close or not (no point refreshing the display for example).
	 */
	bool isClosing() const { return is_closing_; }
	///
	ButtonControllerBase & bc() const;
	/// The LyX kernel is made available through this.
	Kernel & kernel() { return kernel_; }

	/** How the dialog identifies itself to the kernel.
	    It is also set by the Dialogs class.
	 */
	void setName(string const &);
	///
	string const & name() { return name_; }

	///
	void setView(ViewBase *);
	///
	void setButtonController(ButtonControllerBase *);

	/// Different dialogs will have different implementations.
	class Impl;
	///
	void setImpl(Impl *);
	///
	Impl & impl();

	class Impl {
	public:
		///
		Impl(Dialog &);
		///
		virtual ~Impl() {}
		///
		virtual void initialiseParams(string const & data) = 0;
		/// clean-up on hide.
		virtual void clearParams() = 0;
		/// clean-up on hide.
		virtual void dispatchParams() = 0;
		///
		virtual bool isBufferDependent() const = 0;
		///
		virtual bool disconnectOnApply() const = 0;
	protected:
		///
		Dialog & parent_;
	};
	
private:
	///
	void apply();
	///
	ViewBase & view() const;
	///
	bool is_closing_;
	///
	Kernel kernel_;
	///
	string name_;
	///
	boost::scoped_ptr<ButtonControllerBase> bc_ptr_;
	///
	boost::scoped_ptr<ViewBase> view_ptr_;
	///
	boost::scoped_ptr<Impl> impl_ptr_;
};


#endif // DIALOG_H
#include "Kernel.h"

#include "buffer.h"
#include "BufferView.h"
#include "funcrequest.h"
#include "lyxfunc.h"
#include "frontends/Dialogs.h"
#include "frontends/LyXView.h"

Kernel::Kernel(LyXView & lyxview)
	: lyxview_(lyxview)
{}


void Kernel::dispatch(FuncRequest const & fr, bool verbose)
{
	lyxview_.getLyXFunc().dispatch(fr, verbose);
}


void Kernel::updateDialog(string const & name)
{
	lyxview_.getDialogs().update(name);
}


bool Kernel::isBufferAvailable() const
{
	if (!lyxview_.view().get())
                return false;
        return lyxview_.view()->available();
}


bool Kernel::isBufferReadonly() const
{
	if (!lyxview_.buffer())
                return true;
        return lyxview_.buffer()->isReadonly();
}


BufferView * Kernel::bufferview()
{
	return lyxview_.view().get();
}


BufferView const * Kernel::bufferview() const
{
	return lyxview_.view().get();
}


Buffer * Kernel::buffer()
{
	return lyxview_.buffer();
}


Buffer const * Kernel::buffer() const
{
	return lyxview_.buffer();
}
// -*- C++ -*-

#ifndef KERNEL_H
#define KERNEL_H


#include "LString.h"


class Buffer;
class BufferView;
class FuncRequest;
class LyXView;


class Kernel {
public:
	///
	Kernel(LyXView &);
	///
	void dispatch(FuncRequest const &, bool verbose = false);
	/** The Dialog has received a request from the user to update
	    its contents. It must, therefore, ask the kernel to provide
	    this information to Dialog 'name'.
	 */
	void updateDialog(string const & name);
	///
	bool isBufferAvailable() const;
	///
	bool isBufferReadonly() const;
	///
	Buffer * buffer();
	///
	Buffer const * buffer() const;
	///
	BufferView * bufferview();
	///
	BufferView const * bufferview() const;

private:
	LyXView & lyxview_;
};


#endif // KERNEL_H

Reply via email to