void
JXSaveFileDialog::Receive
	(
	JBroadcaster*	sender,
	const Message&	message
	)
{
	JXDirTable* fileBrowser = GetFileBrowser();

	if (sender == itsFileNameInput)
		{
		if (message.Is(JXWidget::kGotFocus))
			{
			itsSaveButton->SetLabel(kSaveLabel);
			UpdateDisplay();
			}
		else if (message.Is(JXWidget::kLostFocus))
			{
			itsSaveButton->SetLabel(kOpenLabel);
			UpdateDisplay();
			}
		else if (message.Is(JTextEditor::kTextChanged) ||
				 message.Is(JTextEditor::kTextSet))
			{
			UpdateDisplay();
			}
		}

	else if (sender == fileBrowser && message.Is(JXDirTable::kFileDblClicked))
		{
		const JXDirTable::FileDblClicked* info =
			dynamic_cast<const JXDirTable::FileDblClicked*>(&message);
		assert( info != NULL );
		const JString fileName = (info->GetDirEntry()).GetName();
		itsFileNameInput->SetText(fileName);
		itsFileNameInput->Focus();
		}

	else
		{
		if (sender == &(fileBrowser->GetTableSelection()))
			{
			UpdateDisplay();
			}
		else if (sender == fileBrowser &&
				 (message.Is(JXWidget::kGotFocus) ||
				  message.Is(JXWidget::kLostFocus)))
			{
			UpdateDisplay();
			}

		JXCSFDialogBase::Receive(sender, message);
		}
}
JBoolean
JXChooseFileDialog::OKToDeactivate()
{
    if (!JXCSFDialogBase::OKToDeactivate())
    {
        return kJFalse;
    }
    else if (Cancelled())
    {
        return kJTrue;
    }

    JXPathInput* pathInput = GetPathInput();
    if (pathInput->HasFocus())
    {
        GoToItsPath();
        return kJFalse;
    }

    JXInputField* filterInput = GetFilterInput();
    if (filterInput->HasFocus())
    {
        AdjustFilter();
        return kJFalse;
    }

    JXDirTable* fileBrowser = GetFileBrowser();
    if (fileBrowser->GoToSelectedDirectory())
    {
        return kJFalse;
    }

    JPtrArray<JDirEntry> entryList(JPtrArrayT::kDeleteAll);
    if (fileBrowser->GetSelection(&entryList))
    {
        const JSize count = entryList.GetElementCount();
        for (JIndex i=1; i<=count; i++)
        {
            JDirEntry* entry = entryList.NthElement(i);
            entry->ForceUpdate();	// check that link hasn't been broken behind our back
            if (!entry->IsFile())
            {
                (GetDirInfo())->ForceUpdate();
                return kJFalse;
            }
        }
        return kJTrue;
    }
    else
    {
        return kJFalse;
    }
}
void
JXChooseFileDialog::UpdateDisplay()
{
    JXCSFDialogBase::UpdateDisplay();

    JXDirTable* dirTable = GetFileBrowser();
    if (dirTable->HasFocus() && !dirTable->HasSelection())
    {
        itsOpenButton->Deactivate();
    }
    else
    {
        itsOpenButton->Activate();
    }
}
void
JXChooseFileDialog::Receive
(
    JBroadcaster*	sender,
    const Message&	message
)
{
    JXDirTable* fileBrowser = GetFileBrowser();

    if (sender == fileBrowser && message.Is(JXDirTable::kFileDblClicked))
    {
        const JXDirTable::FileDblClicked* info =
            dynamic_cast<const JXDirTable::FileDblClicked*>(&message);
        assert( info != NULL );
        if (info->IsActive())
        {
            EndDialog(kJTrue);
        }
    }

    else if (sender == itsSelectAllButton && message.Is(JXButton::kPushed))
    {
        fileBrowser->SelectAll();
    }

    else if (sender == fileBrowser &&
             (message.Is(JXWidget::kGotFocus) ||
              message.Is(JXWidget::kLostFocus)))
    {
        UpdateDisplay();
    }

    else
    {
        if (sender == &(fileBrowser->GetTableSelection()))
        {
            UpdateDisplay();
        }

        JXCSFDialogBase::Receive(sender, message);
    }
}
void
JXSaveFileDialog::UpdateDisplay()
{
	JXCSFDialogBase::UpdateDisplay();

	JXDirTable* table = GetFileBrowser();

	JBoolean saveWoutFocus = kJFalse;
	if (table->HasFocus())
		{
		if ((table->GetTableSelection()).HasSelection())
			{
			itsSaveButton->SetLabel(kOpenLabel);
			}
		else
			{
			itsSaveButton->SetLabel(kSaveLabel);
			saveWoutFocus = kJTrue;
			}
		}

	if ((itsFileNameInput->HasFocus() || saveWoutFocus) &&
		((itsFileNameInput->GetText()).IsEmpty() ||
		 !(GetDirInfo())->IsWritable()))
		{
		itsSaveButton->Deactivate();
		}
	else
		{
		itsSaveButton->Activate();
		}

	if ((itsFileNameInput->GetText()).IsEmpty())
		{
		itsXDSSource->Deactivate();
		}
	else
		{
		itsXDSSource->Activate();
		}
}
JBoolean
JXSaveFileDialog::OKToDeactivate()
{
	if (!JXCSFDialogBase::OKToDeactivate())
		{
		return kJFalse;
		}
	else if (Cancelled())
		{
		return kJTrue;
		}

	JXPathInput* pathInput = GetPathInput();
	if (pathInput->HasFocus())
		{
		GoToItsPath();
		return kJFalse;
		}

	JXInputField* filterInput = GetFilterInput();
	if (filterInput->HasFocus())
		{
		AdjustFilter();
		return kJFalse;
		}

	JXDirTable* fileBrowser = GetFileBrowser();
	if (fileBrowser->HasFocus() && fileBrowser->GoToSelectedDirectory())
		{
		return kJFalse;
		}

	const JString& fileName = itsFileNameInput->GetText();
	if (fileName.IsEmpty())
		{
		(JGetUserNotification())->ReportError("You need to enter a file name.");
		return kJFalse;
		}

	const JString& path     = GetPath();
	const JString fullName  = path + fileName;

	const JBoolean fileExists = JFileExists(fullName);

	if (JDirectoryExists(fullName))
		{
		(JGetUserNotification())->ReportError(
			"This name is already used for a directory.");
		return kJFalse;
		}
	else if (!JDirectoryWritable(path) && !fileExists)
		{
		(JGetUserNotification())->ReportError(
			"You are not allowed to write to this directory.");
		return kJFalse;
		}
	else if (!fileExists)
		{
		*itsFileName = fileName;
		return kJTrue;
		}
	else if (!JFileWritable(fullName))
		{
		(JGetUserNotification())->ReportError(
			"You are not allowed to write to this file.");
		return kJFalse;
		}
	else if ((JGetUserNotification())->AskUserNo("That file already exists.  Replace it?"))
		{
		*itsFileName = fileName;
		return kJTrue;
		}
	else
		{
		return kJFalse;
		}
}
void
JXSaveFileDialog::SetObjects
	(
	JXScrollbarSet*			scrollbarSet,
	JXStaticText*			promptLabel,
	const JCharacter*		prompt,
	JXSaveFileInput*		fileNameInput,
	const JCharacter*		origName,
	JXStaticText*			pathLabel,
	JXPathInput*			pathInput,
	JXPathHistoryMenu*		pathHistory,
	JXStaticText*			filterLabel,
	JXInputField*			filterInput,
	JXStringHistoryMenu*	filterHistory,
	JXTextButton*			saveButton,
	JXTextButton*			cancelButton,
	JXTextButton*			upButton,
	JXTextButton*			homeButton,
	JXTextButton*			desktopButton,
	JXNewDirButton*			newDirButton,
	JXTextCheckbox*			showHiddenCB,
	JXCurrentPathMenu*		currPathMenu,
	const JCharacter*		message
	)
{
	itsSaveButton    = saveButton;
	itsFileNameInput = fileNameInput;

	itsFileNameInput->ShouldBroadcastAllTextChanged(kJTrue);		// want every keypress

	JXWindow* window = scrollbarSet->GetWindow();
	window->SetTitle("Save file");

	SetButtons(itsSaveButton, cancelButton);
	JXCSFDialogBase::SetObjects(
		scrollbarSet, pathLabel, pathInput, pathHistory,
		filterLabel, filterInput, filterHistory,
		itsSaveButton, upButton, homeButton, desktopButton,
		newDirButton, showHiddenCB, currPathMenu, message);

	JXDirTable* table = GetFileBrowser();
	table->AllowSelectFiles(kJFalse, kJFalse);
	table->AllowDblClickInactive(kJTrue);
	promptLabel->SetText(prompt);
	itsFileNameInput->SetText(origName);

	JXDirTable* fileBrowser = GetFileBrowser();
	fileBrowser->ShouldSelectWhenChangePath(kJFalse);

	const JRect frame   = itsFileNameInput->GetFrame();
	const JCoordinate w = frame.height();
	itsXDSSource =
		new JXDirectSaveSource(this, itsFileNameInput, window,
							   JXWidget::kFixedLeft, JXWidget::kFixedBottom,
							   frame.left, frame.top, w, frame.height());
	assert( itsXDSSource != NULL );
	itsFileNameInput->Move(w, 0);
	itsFileNameInput->AdjustSize(-w, 0);

	UpdateDisplay();

	ListenTo(fileBrowser);
	ListenTo(&(fileBrowser->GetTableSelection()));
	ListenTo(itsFileNameInput);

	cancelButton->SetShortcuts("^[");
}
void
JXChooseFileDialog::SetObjects
	(
	JXScrollbarSet*			scrollbarSet,
	JXStaticText*			pathLabel,
	JXPathInput*			pathInput,
	JXPathHistoryMenu*		pathHistory,
	JXStaticText*			filterLabel,
	JXInputField*			filterInput,
	JXStringHistoryMenu*	filterHistory,
	JXTextButton*			openButton,
	JXTextButton*			cancelButton,
	JXTextButton*			upButton,
	JXTextButton*			homeButton,
	JXTextButton*			selectAllButton,
	JXTextCheckbox*			showHiddenCB,
	JXCurrentPathMenu*		currPathMenu,
	const JCharacter*		origName,
	const JCharacter*		message
	)
{
	if (itsSelectMultipleFlag)
		{
		(scrollbarSet->GetWindow())->SetTitle("Choose files");
		}
	else
		{
		(scrollbarSet->GetWindow())->SetTitle("Choose file");
		}

	itsOpenButton      = openButton;
	itsSelectAllButton = selectAllButton;

	SetButtons(openButton, cancelButton);
	JXCSFDialogBase::SetObjects(
		scrollbarSet, pathLabel, pathInput, pathHistory,
		filterLabel, filterInput, filterHistory,
		openButton, upButton, homeButton, NULL, showHiddenCB,
		currPathMenu, message);

	JXDirTable* fileBrowser = GetFileBrowser();
	fileBrowser->AllowSelectFiles(kJTrue, itsSelectMultipleFlag);
	ListenTo(fileBrowser);
	ListenTo(&(fileBrowser->GetTableSelection()));

	if (itsSelectMultipleFlag)
		{
		ListenTo(itsSelectAllButton);
		}
	else
		{
		itsSelectAllButton->Hide();
		}

    cancelButton->SetShortcuts("^[");
    //homeButton->SetShortcuts("#H");
    //upButton->SetShortcuts("#U");
    //showHiddenCB->SetShortcuts("#S");

	// select initial file

	JIndex index;
	if (!JStringEmpty(origName) &&
		fileBrowser->ClosestMatch(origName, &index))
		{
		const JDirEntry& entry = (GetDirInfo())->GetEntry(index);
		if (entry.GetName() == origName)
			{
			fileBrowser->UpdateScrollbars();
			fileBrowser->SelectSingleEntry(index);
			}
		}
}