// This file is part of Visual D
//
// Visual D integrates the D programming language into Visual Studio
// Copyright (c) 2010 by Rainer Schuetze, All Rights Reserved
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
module visuald.propertypage;
import visuald.windows;
import sdk.win32.objbase;
import sdk.win32.winreg;
import sdk.vsi.vsshell;
import sdk.vsi.vsshell80;
import visuald.comutil;
import visuald.logutil;
import visuald.dpackage;
import visuald.dproject;
import visuald.dllmain;
import visuald.config;
import visuald.winctrl;
import visuald.hierarchy;
import visuald.hierutil;
import visuald.pkgutil;
import visuald.chiernode;
import visuald.register;
import stdext.array;
import stdext.path;
import std.array;
import std.string;
import std.conv;
import std.algorithm;
// version = DParserOption;
class PropertyWindow : Window
{
this(Widget parent, uint style, string title, PropertyPage page)
{
mPropertyPage = page;
super(parent, style, title);
}
override int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam)
{
import sdk.win32.commctrl;
switch (uMsg) {
case WM_SIZE:
mPropertyPage.updateSizes();
break;
case TCN_SELCHANGING:
case TCN_SELCHANGE:
// Return FALSE to allow the selection to change.
auto tc = cast(TabControl) this;
return FALSE;
default:
break;
}
return super.WindowProc(hWnd, uMsg, wParam, lParam);
}
PropertyPage mPropertyPage;
}
abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage, IVsPropertyPage2
{
/*const*/ int kPageWidth = 370;
/*const*/ int kPageHeight = 210;
/*const*/ int kMargin = 2;
/*const*/ int kLabelWidth = 120;
/*const*/ int kTextHeight = 20;
/*const*/ int kLineHeight = 23;
/*const*/ int kLineSpacing = 2;
/*const*/ int kNeededLines = 11;
override HRESULT QueryInterface(in IID* riid, void** pvObject)
{
if(queryInterface!(IPropertyPage) (this, riid, pvObject))
return S_OK;
if(queryInterface!(IVsPropertyPage) (this, riid, pvObject))
return S_OK;
if(queryInterface!(IVsPropertyPage2) (this, riid, pvObject))
return S_OK;
return super.QueryInterface(riid, pvObject);
}
override void Dispose()
{
mResizableWidgets = mResizableWidgets.init;
mSite = release(mSite);
foreach(obj; mObjects)
release(obj);
mObjects.length = 0;
mDlgFont = deleteDialogFont(mDlgFont);
}
override int SetPageSite(
/* [in] */ IPropertyPageSite pPageSite)
{
mixin(LogCallMix);
mSite = release(mSite);
mSite = addref(pPageSite);
return S_OK;
}
override int Activate(
/* [in] */ in HWND hWndParent,
/* [in] */ in RECT *pRect,
/* [in] */ in BOOL bModal)
{
mixin(LogCallMix);
if(mWindow)
return returnError(E_FAIL);
return _Activate(new Window(hWndParent), pRect, bModal != 0);
}
int _Activate(Window win, const(RECT) *pRect, bool bModal)
{
updateEnvironmentFont();
if(!mDlgFont)
mDlgFont = newDialogFont();
mWindow = win;
mCanvas = new Window(mWindow);
DWORD color = GetSysColor(COLOR_BTNFACE);
mCanvas.setBackground(color);
// create with desired size to get proper alignment, then resize to parent later
mCanvas.setRect(kMargin, kMargin, kPageWidth - 2 * kMargin, kPageHeight - 2 * kMargin);
// avoid closing canvas (but not dialog) if pressing esc in MultiLineEdit controls
//mCanvas.cancelCloseDelegate ~= delegate bool(Widget c) { return true; };
mCanvas.commandDelegate = &OnCommand;
CreateControls();
UpdateControls();
updateSizes();
mEnableUpdateDirty = true;
return S_OK;
}
extern(D) void OnCommand(Widget w, int cmd)
{
UpdateDirty(true);
}
override int Deactivate()
{
mixin(LogCallMix);
if(mWindow)
{
auto win = mWindow;
mCanvas = null;
mWindow = null;
win.Dispose();
}
return S_OK;
//return returnError(E_NOTIMPL);
}
void updateSizes()
{
if (!mWindow || !mCanvas)
return;
RECT r, pr;
mCanvas.GetWindowRect(&r);
mWindow.GetWindowRect(&pr);
int pageWidth = pr.right - pr.left - 2 * kMargin;
int pageHeight = pr.bottom - pr.top - 2 * kMargin;
if (r.right - r.left == pageWidth && r.bottom - r.top == pageHeight)
return;
mCanvas.setRect(kMargin, kMargin, pageWidth, pageHeight);
updateResizableWidgets(mCanvas);
}
void updateResizableWidgets(Widget w)
{
if (auto patt = w in mResizableWidgets)
patt.resizeWidget(w);
foreach(c; w.children)
updateResizableWidgets(c);
}
void addResizableWidget(Widget w, Attachment att)
{
AttachData attData = AttachData(att);
attData.initFromWidget(w);
mResizableWidgets[w] = attData;
}
void refreshResizableWidget(Widget w)
{
if (auto att = w in mResizableWidgets)
att.initFromWidget(w);
}
void addTextPath(Text ctrl, string path, string sep)
{
string imp = ctrl.getText();
if(!imp.empty() && !imp.endsWith(sep))
imp ~= sep;
imp ~= quoteFilename(path);
ctrl.setText(imp);
}
void addBrowsePath(Text ctrl, bool dir, string reldir, string sep, string title, string filter = null)
{
string path;
if(dir)
path = browseDirectory(mCanvas.hwnd, title, reldir);
else
path = browseFile(mCanvas.hwnd, title, filter, reldir);
if (!path.empty)
{
if(reldir)
path = makeRelative(path, reldir);
addTextPath(ctrl, path, sep);
}
}
void calcMetric()
{
updateEnvironmentFont();
if(!mDlgFont)
mDlgFont = newDialogFont();
HWND hwnd = GetDesktopWindow();
HDC dc = GetDC(hwnd);
SelectObject(dc, mDlgFont);
TEXTMETRIC tm;
GetTextMetrics(dc, &tm);
ReleaseDC(hwnd, dc);
int fHeight = tm.tmHeight;
int fWidth = tm.tmAveCharWidth;
kPageWidth = fWidth * 75 + 2 * kMargin;
kLabelWidth = fWidth * 22;
mUnindentCheckBox = kLabelWidth;
kLineSpacing = 2;
kTextHeight = fHeight + 4;
kLineHeight = kTextHeight + kLineSpacing + 1;
kPageHeight = kLineHeight * kNeededLines + 2 * kMargin;
}
override int GetPageInfo(
/* [out] */ PROPPAGEINFO *pPageInfo)
{
mixin(LogCallMix);
if(pPageInfo.cb < PROPPAGEINFO.sizeof)
return E_INVALIDARG;
calcMetric();
pPageInfo.cb = PROPPAGEINFO.sizeof;
pPageInfo.pszTitle = string2OLESTR("Title");
pPageInfo.size = visuald.comutil.SIZE(kPageWidth, kPageHeight);
pPageInfo.pszHelpFile = string2OLESTR("HelpFile");
pPageInfo.pszDocString = string2OLESTR("DocString");
pPageInfo.dwHelpContext = 0;
return S_OK;
}
override int SetObjects(
/* [in] */ in ULONG cObjects,
/* [size_is][in] */ IUnknown *ppUnk)
{
mixin(LogCallMix2);
foreach(obj; mObjects)
release(obj);
mObjects.length = 0;
for(uint i = 0; i < cObjects; i++)
mObjects ~= addref(ppUnk[i]);
if(mWindow)
{
mEnableUpdateDirty = false;
UpdateControls();
mEnableUpdateDirty = true;
}
return S_OK;
}
override int Show(
/* [in] */ in UINT nCmdShow)
{
logCall("%s.Show(nCmdShow=%s)", this, _toLog(nCmdShow));
if(mWindow)
mWindow.setVisible(true);
return S_OK;
//return returnError(E_NOTIMPL);
}
override int Move(
/* [in] */ in RECT *pRect)
{
mixin(LogCallMix);
updateSizes();
return S_OK; //returnError(E_NOTIMPL);
}
override int Help(
/* [in] */ in wchar* pszHelpDir)
{
logCall("%s.Help(pszHelpDir=%s)", this, _toLog(pszHelpDir));
return returnError(E_NOTIMPL);
}
override int TranslateAccelerator(
/* [in] */ in MSG *pMsg)
{
mixin(LogCallMix2);
if(mSite)
return mSite.TranslateAccelerator(pMsg);
return returnError(E_NOTIMPL);
}
// IVsPropertyPage
override int get_CategoryTitle(
/* [in] */ in UINT iLevel,
/* [retval][out] */ BSTR *pbstrCategory)
{
logCall("%s.get_CategoryTitle(iLevel=%s, pbstrCategory=%s)", this, _toLog(iLevel), _toLog(pbstrCategory));
switch(iLevel)
{
case 0:
if(GetCategoryName().length == 0)
return S_FALSE;
*pbstrCategory = allocBSTR(GetCategoryName());
break;
case 1:
return S_FALSE;
//*pbstrCategory = allocBSTR("CategoryTitle1");
default:
break;
}
return S_OK;
}
// IVsPropertyPage2
override int GetProperty(
/* [in] */ in VSPPPID propid,
/* [out] */ VARIANT *pvar)
{
mixin(LogCallMix);
switch(propid)
{
case VSPPPID_PAGENAME:
pvar.vt = VT_BSTR;
pvar.bstrVal = allocBSTR(GetPageName());
return S_OK;
default:
break;
}
return returnError(DISP_E_MEMBERNOTFOUND);
}
override int SetProperty(
/* [in] */ in VSPPPID propid,
/* [in] */ in VARIANT var)
{
mixin(LogCallMix);
return returnError(E_NOTIMPL);
}
///////////////////////////////////////
void UpdateDirty(bool bDirty)
{
if(mEnableUpdateDirty && mSite)
mSite.OnStatusChange(PROPPAGESTATUS_DIRTY | PROPPAGESTATUS_VALIDATE);
}
static int getWidgetWidth(Widget w, int def)
{
RECT pr;
if(w && w.GetWindowRect(&pr))
return pr.right - pr.left;
return def;
}
void AddControl(string label, Widget w)
{
AddControl(label, w, null, 0);
}
void AddControl(string label, Widget w, Button btn)
{
AddControl(label, w, btn, 0);
}
void AddControl(string label, Widget w, short attachY)
{
AddControl(label, w, null, attachY);
}
void AddControl(string label, Widget w, Button btn, short resizeY)
{
int x = kLabelWidth;
auto cb = cast(CheckBox) w;
auto tc = cast(TabControl) w;
auto mt = cast(MultiLineText) w;
//if(cb)
// cb.cmd = 1; // enable actionDelegate
int lines = 1;
if(mt || tc)
lines = mLinesPerMultiLine;
int pageWidth = getWidgetWidth(w ? w.parent : null, kPageWidth);
if (btn)
pageWidth -= kLineHeight;
int labelWidth = 0;
int margin = tc ? 0 : kMargin;
if(label.length)
{
Label lab = new Label(w ? w.parent : null, label);
int off = ((kLineHeight - kLineSpacing) - 16) / 2;
labelWidth = w ? kLabelWidth : pageWidth - 2*margin;
lab.setRect(0, mLineY + off, labelWidth, kLineHeight - kLineSpacing);
if(mAttachY > 0)
{
Attachment att = kAttachNone;
att.vdiv = 1000;
att.top = att.bottom = mAttachY;
addResizableWidget(lab, att);
}
}
else if (cb || tc)
{
x -= mUnindentCheckBox;
}
int h = lines * kLineHeight - kLineSpacing;
if(cast(Text) w && lines == 1)
{
h = kTextHeight;
}
else if(cb)
h -= 2;
else if(tc)
h += tc.getFrameHeight() - kLineHeight;
//else if(cast(ComboBox) w)
// h -= 4;
int yspacing = (lines * kLineHeight - kLineSpacing - h) / 2;
int y = mLineY + max(0, yspacing);
if(w)
{
w.setRect(x, y, pageWidth - 2*margin - labelWidth, h);
Attachment att = kAttachLeftRight;
att.vdiv = 1000;
att.top = mAttachY;
att.bottom = cast(short)(mAttachY + resizeY);
addResizableWidget(w, att);
}
if(btn)
{
btn.setRect(pageWidth - kMargin, y, kLineHeight, kLineHeight - kLineSpacing);
Attachment att = kAttachRight;
att.vdiv = 1000;
att.top = att.bottom = mAttachY;
addResizableWidget(btn, att);
}
mLineY += max(h, lines * kLineHeight);
mAttachY += resizeY;
}
void AddLabel(string lab)
{
auto w = new Label(mCanvas, lab);
int pageWidth = getWidgetWidth(mCanvas, kPageWidth);
int off = ((kLineHeight - kLineSpacing) - 16) / 2;
w.setRect(0, mLineY + off, pageWidth - 2*kMargin, kLineHeight - kLineSpacing);
Attachment att = kAttachLeftRight;
att.vdiv = 1000;
att.top = att.bottom = mAttachY;
addResizableWidget(w, att);
mLineY += kLineHeight;
}
void AddHorizontalLine()
{
auto w = new Label(mCanvas);
w.AddWindowStyle(SS_ETCHEDFRAME, SS_TYPEMASK);
w.setRect(0, mLineY + 2, getWidgetWidth(mCanvas, kPageWidth) - 2*kMargin, 2);
Attachment att = kAttachLeftRight;
att.vdiv = 1000;
att.top = att.bottom = mAttachY;
addResizableWidget(w, att);
mLineY += 6;
}
int changeOption(V)(V val, ref V optval, ref V refval)
{
if(refval == val)
return 0;
optval = val;
return 1;
}
int changeOptionDg(V)(V val, void delegate (V optval) setdg, V refval)
{
if(refval == val)
return 0;
setdg(val);
return 1;
}
abstract void CreateControls();
abstract void UpdateControls();
abstract string GetCategoryName();
abstract string GetPageName();
AttachData[Widget] mResizableWidgets;
HFONT mDlgFont;
IUnknown[] mObjects;
IPropertyPageSite mSite;
Window mWindow;
Window mCanvas;
bool mEnableUpdateDirty;
int mLineY;
short mAttachY = 0; // fraction of 1000
int mLinesPerMultiLine = 4;
int mUnindentCheckBox = 120; //16;
}
///////////////////////////////////////////////////////////////////////////////
class ProjectPropertyPage : PropertyPage, ConfigModifiedListener
{
abstract void SetControls(ProjectOptions options);
abstract int DoApply(ProjectOptions options, ProjectOptions refoptions);
override HRESULT QueryInterface(in IID* riid, void** pvObject)
{
//if(queryInterface!(ConfigModifiedListener) (this, riid, pvObject))
// return S_OK;
return super.QueryInterface(riid, pvObject);
}
override void UpdateControls()
{
if(ProjectOptions options = GetProjectOptions())
SetControls(options);
}
override void Dispose()
{
if(auto cfg = GetConfig())
cfg.RemoveModifiedListener(this);
super.Dispose();
}
override void OnConfigModified()
{
}
override int SetObjects(/* [in] */ in ULONG cObjects,
/* [size_is][in] */ IUnknown *ppUnk)
{
if(auto cfg = GetConfig())
cfg.RemoveModifiedListener(this);
int rc = super.SetObjects(cObjects, ppUnk);
if(auto cfg = GetConfig())
cfg.AddModifiedListener(this);
return rc;
}
Config GetConfig()
{
if(mObjects.length > 0)
{
auto config = ComPtr!(Config)(mObjects[0]);
return config;
}
return null;
}
ProjectOptions GetProjectOptions()
{
if(auto cfg = GetConfig())
return cfg.GetProjectOptions();
return null;
}
string GetProjectDir()
{
if(auto cfg = GetConfig())
return cfg.GetProjectDir();
return null;
}
/*override*/ int IsPageDirty()
{
mixin(LogCallMix);
if(mWindow)
if(ProjectOptions options = GetProjectOptions())
{
scope ProjectOptions opt = new ProjectOptions(false, false);
return DoApply(opt, options) > 0 ? S_OK : S_FALSE;
}
return S_FALSE;
}
/*override*/ int Apply()
{
mixin(LogCallMix);
if(ProjectOptions refoptions = GetProjectOptions())
{
// make a copy, otherwise changes will no longer be detected after the first configuration
auto refopt = clone(refoptions);
for(int i = 0; i < mObjects.length; i++)
{
auto config = ComPtr!(Config)(mObjects[i]);
if(config)
{
DoApply(config.ptr.GetProjectOptions(), refopt);
config.SetDirty();
}
}
return S_OK;
}
return returnError(E_FAIL);
}
}
class NodePropertyPage : PropertyPage
{
abstract void SetControls(CFileNode node);
abstract int DoApply(CFileNode node, CFileNode refnode);
override void UpdateControls()
{
if(CFileNode node = GetNode())
SetControls(node);
}
CFileNode GetNode()
{
if(mObjects.length > 0)
{
auto node = ComPtr!(CFileNode)(mObjects[0]);
if(node)
return node;
}
return null;
}
/*override*/ int IsPageDirty()
{
mixin(LogCallMix);
if(mWindow)
if(CFileNode node = GetNode())
{
scope CFileNode n = newCom!CFileNode("");
return DoApply(n, node) > 0 ? S_OK : S_FALSE;
}
return S_FALSE;
}
/*override*/ int Apply()
{
mixin(LogCallMix);
if(CFileNode refnode = GetNode())
{
for(int i = 0; i < mObjects.length; i++)
{
auto node = ComPtr!(CFileNode)(mObjects[i]);
if(node)
{
DoApply(node, refnode);
if(CProjectNode pn = cast(CProjectNode) node.GetRootNode())
pn.SetProjectFileDirty(true);
}
}
return S_OK;
}
return returnError(E_FAIL);
}
}
class ResizablePropertyPage : PropertyPage
{
void SetWindowSize(int x, int y, int w, int h)
{
mixin(LogCallMix);
if(mCanvas)
mCanvas.setRect(x, y, w, h);
}
}
class GlobalPropertyPage : ResizablePropertyPage
{
abstract void SetControls(GlobalOptions options);
abstract int DoApply(GlobalOptions options, GlobalOptions refoptions);
this(GlobalOptions options)
{
mOptions = options;
}
override void UpdateControls()
{
if(GlobalOptions options = GetGlobalOptions())
SetControls(options);
}
GlobalOptions GetGlobalOptions()
{
return mOptions;
}
/*override*/ int IsPageDirty()
{
mixin(LogCallMix);
if(mWindow)
if(GlobalOptions options = GetGlobalOptions())
{
scope GlobalOptions opt = new GlobalOptions;
return DoApply(opt, options) > 0 ? S_OK : S_FALSE;
}
return S_FALSE;
}
/*override*/ int Apply()
{
mixin(LogCallMix);
if(GlobalOptions options = GetGlobalOptions())
{
DoApply(options, options);
options.saveToRegistry();
return S_OK;
}
return returnError(E_FAIL);
}
GlobalOptions mOptions;
}
///////////////////////////////////////////////////////////////////////////////
class CommonPropertyPage : ProjectPropertyPage
{
override string GetCategoryName() { return ""; }
override string GetPageName() { return "General"; }
override void CreateControls()
{
AddControl("Build System", mCbBuildSystem = new ComboBox(mCanvas, [ "Visual D", "dsss", "rebuild" ], false));
mCbBuildSystem.setSelection(0);
mCbBuildSystem.setEnabled(false);
}
override void SetControls(ProjectOptions options)
{
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
return 0;
}
ComboBox mCbBuildSystem;
}
class GeneralPropertyPage : ProjectPropertyPage
{
override string GetCategoryName() { return ""; }
override string GetPageName() { return "General"; }
__gshared const float[] selectableVersions = [ 1, 2 ];
override void CreateControls()
{
string[] versions;
foreach(ver; selectableVersions)
versions ~= "D" ~ to!(string)(ver);
//versions[$-1] ~= "+";
AddControl("Compiler", mCompiler = new ComboBox(mCanvas, [ "DMD", "GDC", "LDC" ], false));
AddControl("D-Version", mDVersion = new ComboBox(mCanvas, versions, false));
AddControl("Output Type", mCbOutputType = new ComboBox(mCanvas,
[ "Executable", "Library", "DLL" ], false));
AddControl("Subsystem", mCbSubsystem = new ComboBox(mCanvas,
[ "Not set", "Console", "Windows", "Native", "Posix" ], false));
AddControl("Output Path", mOutputPath = new Text(mCanvas));
AddControl("Intermediate Path", mIntermediatePath = new Text(mCanvas));
AddControl("Files to clean", mFilesToClean = new Text(mCanvas));
AddControl("Compilation", mSingleFileComp = new ComboBox(mCanvas,
[ "Combined compile and link", "Single file compilation",
"Separate compile and link", "Compile only (use Post-build command to link)" ], false));
}
override void SetControls(ProjectOptions options)
{
int ver = 0;
while(ver < selectableVersions.length - 1 && selectableVersions[ver+1] <= options.Dversion)
ver++;
mDVersion.setSelection(ver);
mCompiler.setSelection(options.compiler);
mSingleFileComp.setSelection(options.compilationModel);
mCbOutputType.setSelection(options.lib);
mCbSubsystem.setSelection(options.subsystem);
mOutputPath.setText(options.outdir);
mIntermediatePath.setText(options.objdir);
mFilesToClean.setText(options.filesToClean);
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
float ver = selectableVersions[mDVersion.getSelection()];
int changes = 0;
changes += changeOption(cast(uint) mSingleFileComp.getSelection(), options.compilationModel, refoptions.compilationModel);
changes += changeOption(cast(ubyte) mCbOutputType.getSelection(), options.lib, refoptions.lib);
changes += changeOption(cast(ubyte) mCbSubsystem.getSelection(), options.subsystem, refoptions.subsystem);
changes += changeOption(cast(ubyte) mCompiler.getSelection(), options.compiler, refoptions.compiler);
changes += changeOption(ver, options.Dversion, refoptions.Dversion);
changes += changeOption(mOutputPath.getText(), options.outdir, refoptions.outdir);
changes += changeOption(mIntermediatePath.getText(), options.objdir, refoptions.objdir);
changes += changeOption(mFilesToClean.getText(), options.filesToClean, refoptions.filesToClean);
return changes;
}
ComboBox mCompiler;
ComboBox mSingleFileComp;
ComboBox mCbOutputType;
ComboBox mCbSubsystem;
ComboBox mDVersion;
Text mOutputPath;
Text mIntermediatePath;
Text mFilesToClean;
}
class DebuggingPropertyPage : ProjectPropertyPage
{
override string GetCategoryName() { return ""; }
override string GetPageName() { return "Debugging"; }
enum ID_DBGCOMMAND = 1020;
enum ID_DBGDIR = 1021;
extern(D) override void OnCommand(Widget w, int cmd)
{
switch(cmd)
{
case ID_DBGCOMMAND:
if(auto file = browseFile(mCanvas.hwnd, "Select executable", "Executables\0*.exe\0All Files\0*.*\0"))
mCommand.setText(file);
break;
case ID_DBGDIR:
if(auto dir = browseDirectory(mCanvas.hwnd, "Select working directory"))
mWorkingDir.setText(dir);
break;
default:
break;
}
super.OnCommand(w, cmd);
}
override void CreateControls()
{
Label lbl;
auto btn = new Button(mCanvas, "...", ID_DBGCOMMAND);
AddControl("Command", mCommand = new Text(mCanvas), btn);
AddControl("Command Arguments", mArguments = new Text(mCanvas));
btn = new Button(mCanvas, "...", ID_DBGDIR);
AddControl("Working Directory", mWorkingDir = new Text(mCanvas), btn);
AddControl("", mAttach = new CheckBox(mCanvas, "Attach to running process"));
AddControl("Remote Machine", mRemote = new Text(mCanvas));
AddControl("Debugger", mDebugEngine = new ComboBox(mCanvas, [ "Visual Studio", "Mago", "Visual Studio (x86 Mixed Mode)" ], false));
AddControl("", mStdOutToOutputWindow = new CheckBox(mCanvas, "Redirect stdout to output window"));
AddControl("Run without debugging", lbl = new Label(mCanvas, ""));
AddControl("", mPauseAfterRunning = new CheckBox(mCanvas, "Pause when program finishes"));
lbl.AddWindowExStyle(WS_EX_STATICEDGE);
lbl.AddWindowStyle(SS_ETCHEDFRAME, SS_TYPEMASK);
int left, top, w, h;
if(lbl.getRect(left, top, w, h))
lbl.setRect(left, top + h / 2 - 1, w, 2);
refreshResizableWidget(lbl);
}
override void UpdateDirty(bool bDirty)
{
super.UpdateDirty(bDirty);
EnableControls();
}
void EnableControls()
{
mStdOutToOutputWindow.setEnabled(mDebugEngine.getSelection() != 1);
}
override void SetControls(ProjectOptions options)
{
mCommand.setText(options.debugtarget);
mArguments.setText(options.debugarguments);
mWorkingDir.setText(options.debugworkingdir);
mAttach.setChecked(options.debugattach);
mRemote.setText(options.debugremote);
mDebugEngine.setSelection(options.debugEngine);
mStdOutToOutputWindow.setChecked(options.debugStdOutToOutputWindow);
mPauseAfterRunning.setChecked(options.pauseAfterRunning);
EnableControls();
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
int changes = 0;
changes += changeOption(mCommand.getText(), options.debugtarget, refoptions.debugtarget);
changes += changeOption(mArguments.getText(), options.debugarguments, refoptions.debugarguments);
changes += changeOption(mWorkingDir.getText(), options.debugworkingdir, refoptions.debugworkingdir);
changes += changeOption(mAttach.isChecked(), options.debugattach, options.debugattach);
changes += changeOption(mRemote.getText(), options.debugremote, refoptions.debugremote);
changes += changeOption(cast(ubyte)mDebugEngine.getSelection(), options.debugEngine, refoptions.debugEngine);
changes += changeOption(mStdOutToOutputWindow.isChecked(), options.debugStdOutToOutputWindow, options.debugStdOutToOutputWindow);
changes += changeOption(mPauseAfterRunning.isChecked(), options.pauseAfterRunning, options.pauseAfterRunning);
return changes;
}
Text mCommand;
Text mArguments;
Text mWorkingDir;
Text mRemote;
CheckBox mAttach;
ComboBox mDebugEngine;
CheckBox mStdOutToOutputWindow;
CheckBox mPauseAfterRunning;
}
class DmdGeneralPropertyPage : ProjectPropertyPage
{
override string GetCategoryName() { return "Compiler"; }
override string GetPageName() { return "General"; }
enum ID_IMPORTPATH = 1030;
enum ID_STRINGIMPORTPATH = 1031;
void addImportDir(Text ctrl, string title)
{
addBrowsePath(ctrl, true, GetProjectDir(), ";", title);
}
extern(D) override void OnCommand(Widget w, int cmd)
{
switch(cmd)
{
case ID_IMPORTPATH:
addImportDir(mAddImports, "Add import path");
break;
case ID_STRINGIMPORTPATH:
addImportDir(mStringImports, "Add string import path");
break;
default:
break;
}
super.OnCommand(w, cmd);
}
override void CreateControls()
{
AddControl("", mDepImports = new CheckBox(mCanvas, "Add import paths of project dependencies"));
auto btn = new Button(mCanvas, "+", ID_IMPORTPATH);
AddControl("Additional Import Paths", mAddImports = new Text(mCanvas), btn);
btn = new Button(mCanvas, "+", ID_STRINGIMPORTPATH);
AddControl("String Import Paths", mStringImports = new Text(mCanvas), btn);
AddControl("Version Identifiers", mVersionIdentifiers = new Text(mCanvas));
AddControl("Debug Identifiers", mDebugIdentifiers = new Text(mCanvas));
AddHorizontalLine();
AddControl("", mOtherDMD = new CheckBox(mCanvas, "Use other compiler"));
AddControl("Compiler Path", mCompilerPath = new Text(mCanvas));
AddHorizontalLine();
AddControl("C/C++ Compiler Cmd", mCCCmd = new Text(mCanvas));
AddControl("", mTransOpt = new CheckBox(mCanvas, "Translate D options (debug, optimizations)"));
}
override void UpdateDirty(bool bDirty)
{
super.UpdateDirty(bDirty);
EnableControls();
}
void EnableControls()
{
mCompilerPath.setEnabled(mOtherDMD.isChecked());
}
override void SetControls(ProjectOptions options)
{
mDepImports.setChecked(options.addDepImp);
mAddImports.setText(options.imppath);
mStringImports.setText(options.fileImppath);
mVersionIdentifiers.setText(options.versionids);
mDebugIdentifiers.setText(options.debugids);
mOtherDMD.setChecked(options.otherDMD);
mCompilerPath.setText(options.program);
mCCCmd.setText(options.cccmd);
mTransOpt.setChecked(options.ccTransOpt);
EnableControls();
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
int changes = 0;
changes += changeOption(mDepImports.isChecked(), options.addDepImp, refoptions.addDepImp);
changes += changeOption(mAddImports.getText(), options.imppath, refoptions.imppath);
changes += changeOption(mStringImports.getText(), options.fileImppath, refoptions.fileImppath);
changes += changeOption(mVersionIdentifiers.getText(), options.versionids, refoptions.versionids);
changes += changeOption(mDebugIdentifiers.getText(), options.debugids, refoptions.debugids);
changes += changeOption(mOtherDMD.isChecked(), options.otherDMD, refoptions.otherDMD);
changes += changeOption(mCompilerPath.getText(), options.program, refoptions.program);
changes += changeOption(mCCCmd.getText(), options.cccmd, refoptions.cccmd);
changes += changeOption(mTransOpt.isChecked(), options.ccTransOpt, refoptions.ccTransOpt);
return changes;
}
CheckBox mDepImports;
Text mAddImports;
Text mStringImports;
Text mVersionIdentifiers;
Text mDebugIdentifiers;
CheckBox mOtherDMD;
Text mCompilerPath;
Text mCCCmd;
CheckBox mTransOpt;
}
class DmdDebugPropertyPage : ProjectPropertyPage
{
override string GetCategoryName() { return "Compiler"; }
override string GetPageName() { return "Debug"; }
enum ID_BROWSECV2PDB = 1010;
extern(D) override void OnCommand(Widget w, int cmd)
{
switch(cmd)
{
case ID_BROWSECV2PDB:
if(auto file = browseFile(mCanvas.hwnd, "Select cv2pdb executable", "Executables\0*.exe\0All Files\0*.*\0"))
mPathCv2pdb.setText(file);
break;
default:
break;
}
super.OnCommand(w, cmd);
}
override void CreateControls()
{
string[] dbgInfoOpt = [ "None", "Symbolic (suitable for Mago)", "Symbolic (suitable for VS debug engine)", "Symbolic (suitable for selected debug engine)" ];
AddControl("Debug Mode", mDebugMode = new ComboBox(mCanvas, [ "On (enable debug statements, asserts, invariants and constraints)",
"Off (disable asserts, invariants and constraints)",
"Default (enable asserts, invariants and constraints)" ], false));
AddControl("Debug Info", mDebugInfo = new ComboBox(mCanvas, dbgInfoOpt, false));
AddHorizontalLine();
string[] cv2pdbOpt = [ "Never", "If recommended for selected debug engine", "Always" ];
AddControl("Run cv2pdb", mRunCv2pdb = new ComboBox(mCanvas, cv2pdbOpt, false));
auto btn = new Button(mCanvas, "...", ID_BROWSECV2PDB);
AddControl("Path to cv2pdb", mPathCv2pdb = new Text(mCanvas), btn);
AddControl("", mCv2pdbPre2043 = new CheckBox(mCanvas, "Assume old associative array implementation (before dmd 2.043)"));
AddControl("", mCv2pdbNoDemangle = new CheckBox(mCanvas, "Do not demangle symbols"));
AddControl("", mCv2pdbEnumType = new CheckBox(mCanvas, "Use enumerator types"));
AddControl("More options", mCv2pdbOptions = new Text(mCanvas));
}
override void UpdateDirty(bool bDirty)
{
super.UpdateDirty(bDirty);
EnableControls();
}
void EnableControls()
{
mRunCv2pdb.setEnabled(mCanRunCv2PDB);
bool runcv2pdb = mCanRunCv2PDB && mRunCv2pdb.getSelection() > 0;
mPathCv2pdb.setEnabled(runcv2pdb);
mCv2pdbOptions.setEnabled(runcv2pdb);
mCv2pdbEnumType.setEnabled(runcv2pdb);
mCv2pdbPre2043.setEnabled(runcv2pdb);
mCv2pdbNoDemangle.setEnabled(runcv2pdb);
}
override void SetControls(ProjectOptions options)
{
mDebugMode.setSelection(options.release);
mDebugInfo.setSelection(options.symdebug);
mRunCv2pdb.setSelection(options.runCv2pdb);
mPathCv2pdb.setText(options.pathCv2pdb);
mCv2pdbOptions.setText(options.cv2pdbOptions);
mCv2pdbPre2043.setChecked(options.cv2pdbPre2043);
mCv2pdbNoDemangle.setChecked(options.cv2pdbNoDemangle);
mCv2pdbEnumType.setChecked(options.cv2pdbEnumType);
mCanRunCv2PDB = options.compiler != Compiler.DMD || (!options.isX86_64 && !options.mscoff);
EnableControls();
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
int changes = 0;
changes += changeOption(cast(ubyte) mDebugMode.getSelection(), options.release, refoptions.release);
changes += changeOption(cast(ubyte) mDebugInfo.getSelection(), options.symdebug, refoptions.symdebug);
changes += changeOption(cast(ubyte) mRunCv2pdb.getSelection(), options.runCv2pdb, refoptions.runCv2pdb);
changes += changeOption(mPathCv2pdb.getText(), options.pathCv2pdb, refoptions.pathCv2pdb);
changes += changeOption(mCv2pdbOptions.getText(), options.cv2pdbOptions, refoptions.cv2pdbOptions);
changes += changeOption(mCv2pdbPre2043.isChecked(), options.cv2pdbPre2043, refoptions.cv2pdbPre2043);
changes += changeOption(mCv2pdbNoDemangle.isChecked(), options.cv2pdbNoDemangle, refoptions.cv2pdbNoDemangle);
changes += changeOption(mCv2pdbEnumType.isChecked(), options.cv2pdbEnumType, refoptions.cv2pdbEnumType);
return changes;
}
bool mCanRunCv2PDB;
ComboBox mDebugMode;
ComboBox mDebugInfo;
ComboBox mRunCv2pdb;
Text mPathCv2pdb;
CheckBox mCv2pdbPre2043;
CheckBox mCv2pdbNoDemangle;
CheckBox mCv2pdbEnumType;
Text mCv2pdbOptions;
}
class DmdCodeGenPropertyPage : ProjectPropertyPage
{
this()
{
kNeededLines = 12;
}
override string GetCategoryName() { return "Compiler"; }
override string GetPageName() { return "Code Generation"; }
override void CreateControls()
{
mUnindentCheckBox = kLabelWidth;
AddControl("", mProfiling = new CheckBox(mCanvas, "Insert Profiling Hooks"));
AddControl("", mCodeCov = new CheckBox(mCanvas, "Generate Code Coverage"));
AddControl("", mUnitTests = new CheckBox(mCanvas, "Generate Unittest Code"));
AddHorizontalLine();
AddControl("", mOptimizer = new CheckBox(mCanvas, "Run Optimizer"));
AddControl("", mNoboundscheck = new CheckBox(mCanvas, "No Array Bounds Checking"));
AddControl("", mInline = new CheckBox(mCanvas, "Expand Inline Functions"));
AddHorizontalLine();
AddControl("", mNoFloat = new CheckBox(mCanvas, "No Floating Point Support"));
AddControl("", mGenStackFrame = new CheckBox(mCanvas, "Always generate stack frame (DMD 2.056+)"));
AddControl("", mStackStomp = new CheckBox(mCanvas, "Add stack stomp code (DMD 2.062+)"));
AddControl("", mAllInst = new CheckBox(mCanvas, "Generate code for all template instantiations (DMD 2.064+)"));
}
override void SetControls(ProjectOptions options)
{
mProfiling.setChecked(options.trace);
mCodeCov.setChecked(options.cov);
mOptimizer.setChecked(options.optimize);
mNoboundscheck.setChecked(options.noboundscheck);
mUnitTests.setChecked(options.useUnitTests);
mInline.setChecked(options.useInline);
mNoFloat.setChecked(options.nofloat);
mGenStackFrame.setChecked(options.genStackFrame);
mStackStomp.setChecked(options.stackStomp);
mAllInst.setChecked(options.allinst);
mNoboundscheck.setEnabled(options.Dversion > 1);
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
int changes = 0;
changes += changeOption(mCodeCov.isChecked(), options.cov, refoptions.cov);
changes += changeOption(mProfiling.isChecked(), options.trace, refoptions.trace);
changes += changeOption(mOptimizer.isChecked(), options.optimize, refoptions.optimize);
changes += changeOption(mNoboundscheck.isChecked(), options.noboundscheck, refoptions.noboundscheck);
changes += changeOption(mUnitTests.isChecked(), options.useUnitTests, refoptions.useUnitTests);
changes += changeOption(mInline.isChecked(), options.useInline, refoptions.useInline);
changes += changeOption(mNoFloat.isChecked(), options.nofloat, refoptions.nofloat);
changes += changeOption(mGenStackFrame.isChecked(), options.genStackFrame, refoptions.genStackFrame);
changes += changeOption(mStackStomp.isChecked(), options.stackStomp, refoptions.stackStomp);
changes += changeOption(mAllInst.isChecked(), options.allinst, refoptions.allinst);
return changes;
}
CheckBox mCodeCov;
CheckBox mProfiling;
CheckBox mOptimizer;
CheckBox mNoboundscheck;
CheckBox mUnitTests;
CheckBox mInline;
CheckBox mNoFloat;
CheckBox mGenStackFrame;
CheckBox mStackStomp;
CheckBox mAllInst;
}
class DmdMessagesPropertyPage : ProjectPropertyPage
{
override string GetCategoryName() { return "Compiler"; }
override string GetPageName() { return "Messages"; }
override void CreateControls()
{
mUnindentCheckBox = kLabelWidth;
AddControl("", mWarnings = new CheckBox(mCanvas, "Enable Warnings"));
AddControl("", mInfoWarnings = new CheckBox(mCanvas, "Enable Informational Warnings (DMD 2.041+)"));
AddHorizontalLine();
AddControl("", mUseDeprecated = new CheckBox(mCanvas, "Silently Allow Deprecated Features"));
AddControl("", mErrDeprecated = new CheckBox(mCanvas, "Use of Deprecated Features causes Error (DMD 2.061+)"));
AddHorizontalLine();
AddControl("", mVerbose = new CheckBox(mCanvas, "Verbose Compile"));
AddControl("", mVtls = new CheckBox(mCanvas, "Show TLS Variables"));
AddControl("", mVgc = new CheckBox(mCanvas, "List all gc allocations including hidden ones (DMD 2.066+)"));
AddControl("", mIgnorePragmas = new CheckBox(mCanvas, "Ignore Unsupported Pragmas"));
AddControl("", mCheckProperty = new CheckBox(mCanvas, "Enforce Property Syntax (DMD 2.055+)"));
}
override void SetControls(ProjectOptions options)
{
mWarnings.setChecked(options.warnings);
mInfoWarnings.setChecked(options.infowarnings);
mVerbose.setChecked(options.verbose);
mVtls.setChecked(options.vtls);
mVgc.setChecked(options.vgc);
mUseDeprecated.setChecked(options.useDeprecated);
mErrDeprecated.setChecked(options.errDeprecated);
mIgnorePragmas.setChecked(options.ignoreUnsupportedPragmas);
mCheckProperty.setChecked(options.checkProperty);
mVtls.setEnabled(options.Dversion > 1);
mVgc.setEnabled(options.Dversion > 1);
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
int changes = 0;
changes += changeOption(mWarnings.isChecked(), options.warnings, refoptions.warnings);
changes += changeOption(mInfoWarnings.isChecked(), options.infowarnings, refoptions.infowarnings);
changes += changeOption(mVerbose.isChecked(), options.verbose, refoptions.verbose);
changes += changeOption(mVtls.isChecked(), options.vtls, refoptions.vtls);
changes += changeOption(mVgc.isChecked(), options.vgc, refoptions.vgc);
changes += changeOption(mUseDeprecated.isChecked(), options.useDeprecated, refoptions.useDeprecated);
changes += changeOption(mErrDeprecated.isChecked(), options.errDeprecated, refoptions.errDeprecated);
changes += changeOption(mIgnorePragmas.isChecked(), options.ignoreUnsupportedPragmas, refoptions.ignoreUnsupportedPragmas);
changes += changeOption(mCheckProperty.isChecked(), options.checkProperty, refoptions.checkProperty);
return changes;
}
CheckBox mWarnings;
CheckBox mInfoWarnings;
CheckBox mVerbose;
CheckBox mVtls;
CheckBox mVgc;
CheckBox mUseDeprecated;
CheckBox mErrDeprecated;
CheckBox mIgnorePragmas;
CheckBox mCheckProperty;
}
class DmdDocPropertyPage : ProjectPropertyPage
{
override string GetCategoryName() { return "Compiler"; }
override string GetPageName() { return "Documentation"; }
override void CreateControls()
{
AddControl("", mGenDoc = new CheckBox(mCanvas, "Generate documentation"));
AddControl("Documentation file", mDocFile = new Text(mCanvas));
AddControl("Documentation dir", mDocDir = new Text(mCanvas));
AddControl("CanDyDOC module", mModulesDDoc = new Text(mCanvas));
AddControl("", mGenHdr = new CheckBox(mCanvas, "Generate interface headers"));
AddControl("Header file", mHdrFile = new Text(mCanvas));
AddControl("Header directory", mHdrDir = new Text(mCanvas));
AddControl("", mGenJSON = new CheckBox(mCanvas, "Generate JSON file"));
AddControl("JSON file", mJSONFile = new Text(mCanvas));
}
override void UpdateDirty(bool bDirty)
{
super.UpdateDirty(bDirty);
EnableControls();
}
void EnableControls()
{
mDocDir.setEnabled(mGenDoc.isChecked());
mDocFile.setEnabled(mGenDoc.isChecked());
mModulesDDoc.setEnabled(mGenDoc.isChecked());
mHdrDir.setEnabled(mGenHdr.isChecked());
mHdrFile.setEnabled(mGenHdr.isChecked());
mJSONFile.setEnabled(mGenJSON.isChecked());
}
override void SetControls(ProjectOptions options)
{
mGenDoc.setChecked(options.doDocComments);
mDocDir.setText(options.docdir);
mDocFile.setText(options.docname);
mModulesDDoc.setText(options.modules_ddoc);
mGenHdr.setChecked(options.doHdrGeneration);
mHdrDir.setText(options.hdrdir);
mHdrFile.setText(options.hdrname);
mGenJSON.setChecked(options.doXGeneration);
mJSONFile.setText(options.xfilename);
EnableControls();
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
int changes = 0;
changes += changeOption(mGenDoc.isChecked(), options.doDocComments, refoptions.doDocComments);
changes += changeOption(mDocDir.getText(), options.docdir, refoptions.docdir);
changes += changeOption(mDocFile.getText(), options.docname, refoptions.docname);
changes += changeOption(mModulesDDoc.getText(), options.modules_ddoc, refoptions.modules_ddoc);
changes += changeOption(mGenHdr.isChecked(), options.doHdrGeneration, refoptions.doHdrGeneration);
changes += changeOption(mHdrDir.getText(), options.hdrdir, refoptions.hdrdir);
changes += changeOption(mHdrFile.getText(), options.hdrname, refoptions.hdrname);
changes += changeOption(mGenJSON.isChecked(), options.doXGeneration, refoptions.doXGeneration);
changes += changeOption(mJSONFile.getText(), options.xfilename, refoptions.xfilename);
return changes;
}
CheckBox mGenDoc;
Text mDocDir;
Text mDocFile;
Text mModulesDDoc;
CheckBox mGenHdr;
Text mHdrDir;
Text mHdrFile;
CheckBox mGenJSON;
Text mJSONFile;
}
class DmdOutputPropertyPage : ProjectPropertyPage
{
override string GetCategoryName() { return "Compiler"; }
override string GetPageName() { return "Output"; }
override void CreateControls()
{
mUnindentCheckBox = kLabelWidth;
AddControl("", mMultiObj = new CheckBox(mCanvas, "Multiple Object Files"));
AddControl("", mPreservePaths = new CheckBox(mCanvas, "Keep Path From Source File"));
AddControl("", mMsCoff32 = new CheckBox(mCanvas, "Use MS-COFF object file format for Win32 (DMD 2.067+)"));
}
override void SetControls(ProjectOptions options)
{
mMultiObj.setChecked(options.multiobj);
mPreservePaths.setChecked(options.preservePaths);
mMsCoff32.setChecked(options.mscoff);
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
int changes = 0;
changes += changeOption(mMultiObj.isChecked(), options.multiobj, refoptions.multiobj);
changes += changeOption(mPreservePaths.isChecked(), options.preservePaths, refoptions.preservePaths);
changes += changeOption(mMsCoff32.isChecked(), options.mscoff, refoptions.mscoff);
return changes;
}
CheckBox mMultiObj;
CheckBox mPreservePaths;
CheckBox mMsCoff32;
}
class DmdLinkerPropertyPage : ProjectPropertyPage
{
override string GetCategoryName() { return "Linker"; }
override string GetPageName() { return "General"; }
this()
{
kNeededLines = 11;
}
override void UpdateDirty(bool bDirty)
{
super.UpdateDirty(bDirty);
EnableControls();
}
enum ID_OBJECTFILES = 1050;
enum ID_LIBRARYFILES = 1051;
enum ID_LIBRARYPATHS = 1052;
enum ID_DEFFILE = 1053;
enum ID_RESFILE = 1054;
extern(D) override void OnCommand(Widget w, int cmd)
{
switch(cmd)
{
case ID_OBJECTFILES:
addBrowsePath(mObjFiles, false, GetProjectDir(), " ", "Add object file", "Object files\0*.obj\0All Files\0*.*\0");
break;
case ID_LIBRARYFILES:
addBrowsePath(mLibFiles, false, GetProjectDir(), " ", "Add library file", "Library files\0*.lib\0All Files\0*.*\0");
break;
case ID_LIBRARYPATHS:
addBrowsePath(mLibPaths, true, GetProjectDir(), " ", "Add library path");
break;
case ID_DEFFILE:
if(auto file = browseFile(mCanvas.hwnd, "Select definition file", "Definition files\0*.def\0All Files\0*.*\0", GetProjectDir()))
mDefFile.setText(makeRelative(file, GetProjectDir()));
break;
case ID_RESFILE:
if(auto file = browseFile(mCanvas.hwnd, "Select resource file", "Resource files\0*.res\0All Files\0*.*\0", GetProjectDir()))
mResFile.setText(makeRelative(file, GetProjectDir()));
break;
default:
break;
}
super.OnCommand(w, cmd);
}
override void CreateControls()
{
AddControl("Output File", mExeFile = new Text(mCanvas));
auto btn = new Button(mCanvas, "+", ID_OBJECTFILES);
AddControl("Object Files", mObjFiles = new Text(mCanvas), btn);
btn = new Button(mCanvas, "+", ID_LIBRARYFILES);
AddControl("Library Files", mLibFiles = new Text(mCanvas), btn);
btn = new Button(mCanvas, "+", ID_LIBRARYPATHS);
AddControl("Library Search Path", mLibPaths = new Text(mCanvas), btn);
//AddControl("Library search paths only work if you have modified sc.ini to include DMD_LIB!", null);
btn = new Button(mCanvas, "...", ID_DEFFILE);
AddControl("Definition File", mDefFile = new Text(mCanvas), btn);
btn = new Button(mCanvas, "...", ID_RESFILE);
AddControl("Resource File", mResFile = new Text(mCanvas), btn);
AddControl("Generate Map File", mGenMap = new ComboBox(mCanvas,
[ "Minimum", "Symbols By Address", "Standard", "Full", "With cross references" ], false));
AddControl("", mImplib = new CheckBox(mCanvas, "Create import library"));
AddControl("", mPrivatePhobos = new CheckBox(mCanvas, "Build and use local version of phobos with same compiler options"));
AddControl("", mUseStdLibPath = new CheckBox(mCanvas, "Use global and standard library search paths"));
AddControl("C Runtime", mCRuntime = new ComboBox(mCanvas, [ "None", "Static Release (LIBCMT)", "Static Debug (LIBCMTD)", "Dynamic Release (MSCVRT)", "Dynamic Debug (MSCVRTD)" ], false));
}
void EnableControls()
{
if(ProjectOptions options = GetProjectOptions())
mCRuntime.setEnabled(options.isX86_64 || options.mscoff);
}
override void SetControls(ProjectOptions options)
{
mExeFile.setText(options.exefile);
mObjFiles.setText(options.objfiles);
mLibFiles.setText(options.libfiles);
mLibPaths.setText(options.libpaths);
mDefFile.setText(options.deffile);
mResFile.setText(options.resfile);
mGenMap.setSelection(options.mapverbosity);
mImplib.setChecked(options.createImplib);
mUseStdLibPath.setChecked(options.useStdLibPath);
mPrivatePhobos.setChecked(options.privatePhobos);
mCRuntime.setSelection(options.cRuntime);
EnableControls();
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
int changes = 0;
changes += changeOption(mExeFile.getText(), options.exefile, refoptions.exefile);
changes += changeOption(mObjFiles.getText(), options.objfiles, refoptions.objfiles);
changes += changeOption(mLibFiles.getText(), options.libfiles, refoptions.libfiles);
changes += changeOption(mLibPaths.getText(), options.libpaths, refoptions.libpaths);
changes += changeOption(mDefFile.getText(), options.deffile, refoptions.deffile);
changes += changeOption(mResFile.getText(), options.resfile, refoptions.resfile);
changes += changeOption(cast(uint) mGenMap.getSelection(), options.mapverbosity, refoptions.mapverbosity);
changes += changeOption(mImplib.isChecked(), options.createImplib, refoptions.createImplib);
changes += changeOption(mUseStdLibPath.isChecked(), options.useStdLibPath, refoptions.useStdLibPath);
changes += changeOption(mPrivatePhobos.isChecked(), options.privatePhobos, refoptions.privatePhobos);
changes += changeOption(cast(uint) mCRuntime.getSelection(), options.cRuntime, refoptions.cRuntime);
return changes;
}
Text mExeFile;
Text mObjFiles;
Text mLibFiles;
Text mLibPaths;
Text mDefFile;
Text mResFile;
ComboBox mGenMap;
CheckBox mImplib;
CheckBox mUseStdLibPath;
CheckBox mPrivatePhobos;
ComboBox mCRuntime;
}
class DmdEventsPropertyPage : ProjectPropertyPage
{
override string GetCategoryName() { return ""; }
override string GetPageName() { return "Build Events"; }
override void CreateControls()
{
mLinesPerMultiLine = 5;
AddControl("Pre-Build Command", mPreCmd = new MultiLineText(mCanvas), 500);
AddControl("Post-Build Command", mPostCmd = new MultiLineText(mCanvas), 500);
Label lab = new Label(mCanvas, "Use \"if errorlevel 1 goto reportError\" to cancel on error");
lab.setRect(0, mLineY, getWidgetWidth(mCanvas, kPageWidth), kLineHeight);
addResizableWidget(lab, kAttachBottom);
}
override void SetControls(ProjectOptions options)
{
mPreCmd.setText(options.preBuildCommand);
mPostCmd.setText(options.postBuildCommand);
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
int changes = 0;
changes += changeOption(mPreCmd.getText(), options.preBuildCommand, refoptions.preBuildCommand);
changes += changeOption(mPostCmd.getText(), options.postBuildCommand, refoptions.postBuildCommand);
return changes;
}
MultiLineText mPreCmd;
MultiLineText mPostCmd;
}
class DmdCmdLinePropertyPage : ProjectPropertyPage
{
override string GetCategoryName() { return ""; }
override string GetPageName() { return "Command line"; }
override void CreateControls()
{
mLinesPerMultiLine = 5;
AddControl("Command line", mCmdLine = new MultiLineText(mCanvas, "", 0, true), 500);
AddControl("Additional options", mAddOpt = new MultiLineText(mCanvas), 500);
}
override void OnConfigModified()
{
if(ProjectOptions options = GetProjectOptions())
if(mCmdLine && mCmdLine.hwnd)
mCmdLine.setText(options.buildCommandLine(GetConfig(), true, true, options.getDependenciesPath()));
}
override void SetControls(ProjectOptions options)
{
mCmdLine.setText(options.buildCommandLine(GetConfig(), true, true, options.getDependenciesPath()));
mAddOpt.setText(options.additionalOptions);
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
int changes = 0;
changes += changeOption(mAddOpt.getText(), options.additionalOptions, refoptions.additionalOptions);
return changes;
}
MultiLineText mCmdLine;
MultiLineText mAddOpt;
}
class ConfigNodePropertyPage : ProjectPropertyPage
{
abstract void SetControls(CFileNode node);
abstract int DoApply(CFileNode node, CFileNode refnode, Config cfg);
override void SetControls(ProjectOptions options)
{
mNodes = GetSelectedNodes();
if(auto node = GetNode())
SetControls(node);
}
override int DoApply(ProjectOptions options, ProjectOptions refoptions)
{
return 0;
}
CHierNode[] GetSelectedNodes()
{
if(auto cfg = GetConfig()) // any config works
{
auto prj = cfg.GetProject();
CHierNode[] nodes;
prj.GetSelectedNodes(nodes);
return nodes;
}
return null;
}
CFileNode GetNode()
{
for(size_t i = 0; i < mNodes.length; i++)
if(auto node = cast(CFileNode)mNodes[i])
return node;
return null;
}
override int IsPageDirty()
{
mixin(LogCallMix);
if(mWindow)
if(CFileNode node = GetNode())
{
Config cfg = GetConfig();
scope CFileNode n = newCom!CFileNode("");
return DoApply(n, node, cfg) > 0 ? S_OK : S_FALSE;
}
return S_FALSE;
}
override int Apply()
{
mixin(LogCallMix);
if(CFileNode rnode = GetNode())
{
auto refnode = rnode.cloneDeep();
for(int i = 0; i < mObjects.length; i++)
{
auto config = ComPtr!(Config)(mObjects[i]);
if(config)
{
for(size_t n = 0; n < mNodes.length; n++)
if(auto node = cast(CFileNode)mNodes[n])
{
DoApply(node, refnode, config);
if(CProjectNode pn = cast(CProjectNode) node.GetRootNode())
pn.SetProjectFileDirty(true);
}
}
return S_OK;
}
}
return returnError(E_FAIL);
}
CHierNode[] mNodes;
}
class FilePropertyPage : ConfigNodePropertyPage
{
override string GetCategoryName() { return ""; }
override string GetPageName() { return "File"; }
override void CreateControls()
{
mLinesPerMultiLine = 3;
AddControl("", mPerConfig = new CheckBox(mCanvas, "per Configuration Options (apply and reopen dialog to update)"));
AddControl("Build Tool", mTool = new ComboBox(mCanvas, [ "Auto", "DMD", kToolCpp, kToolResourceCompiler, "Custom", "None" ], false));
AddControl("Additional Options", mAddOpt = new Text(mCanvas));
AddControl("Build Command", mCustomCmd = new MultiLineText(mCanvas), 1000);
AddControl("Other Dependencies", mDependencies = new Text(mCanvas));
AddControl("Output File", mOutFile = new Text(mCanvas));
AddControl("", mLinkOut = new CheckBox(mCanvas, "Add output to link"));
AddControl("", mUptodateWithSameTime = new CheckBox(mCanvas, "Assume output up to date with same time as input"));
}
override void UpdateDirty(bool bDirty)
{
super.UpdateDirty(bDirty);
enableControls(mTool.getText());
}
void enableControls(string tool)
{
bool perConfigChanged = mInitPerConfig != mPerConfig.isChecked();
bool isCustom = (tool == "Custom");
bool isRc = (tool == kToolResourceCompiler);
bool isCpp = (tool == kToolCpp);
mTool.setEnabled(!perConfigChanged);
mCustomCmd.setEnabled(!perConfigChanged && isCustom);
mAddOpt.setEnabled(!perConfigChanged && (isRc || isCpp));
mDependencies.setEnabled(!perConfigChanged && (isCustom || isRc));
mOutFile.setEnabled(!perConfigChanged && isCustom);
mLinkOut.setEnabled(!perConfigChanged && isCustom);
mUptodateWithSameTime.setEnabled(!perConfigChanged && isCustom);
}
string GetCfgName()
{
return GetConfig().getCfgName();
}
override void SetControls(CFileNode node)
{
string cfgname = GetCfgName();
string tool = node.GetTool(cfgname);
if(tool.length == 0)
mTool.setSelection(0);
else
mTool.setSelection(mTool.findString(tool));
mInitPerConfig = node.GetPerConfigOptions();
mPerConfig.setChecked(mInitPerConfig);
mCustomCmd.setText(node.GetCustomCmd(cfgname));
mAddOpt.setText(node.GetAdditionalOptions(cfgname));
mDependencies.setText(node.GetDependencies(cfgname));
mOutFile.setText(node.GetOutFile(cfgname));
mLinkOut.setChecked(node.GetLinkOutput(cfgname));
mUptodateWithSameTime.setChecked(node.GetUptodateWithSameTime(cfgname));
enableControls(tool);
}
override int DoApply(CFileNode node, CFileNode refnode, Config cfg)
{
string cfgname = GetCfgName();
int changes = 0;
string tool = mTool.getText();
if(tool == "Auto")
tool = "";
changes += changeOptionDg!bool(mPerConfig.isChecked(), &node.SetPerConfigOptions, refnode.GetPerConfigOptions());
changes += changeOptionDg!string(tool, (s) => node.SetTool(cfgname, s), refnode.GetTool(cfgname));
changes += changeOptionDg!string(mCustomCmd.getText(), (s) => node.SetCustomCmd(cfgname, s), refnode.GetCustomCmd(cfgname));
changes += changeOptionDg!string(mAddOpt.getText(), (s) => node.SetAdditionalOptions(cfgname, s), refnode.GetAdditionalOptions(cfgname));
changes += changeOptionDg!string(mDependencies.getText(), (s) => node.SetDependencies(cfgname, s), refnode.GetDependencies(cfgname));
changes += changeOptionDg!string(mOutFile.getText(), (s) => node.SetOutFile(cfgname, s), refnode.GetOutFile(cfgname));
changes += changeOptionDg!bool(mLinkOut.isChecked(), (b) => node.SetLinkOutput(cfgname, b), refnode.GetLinkOutput(cfgname));
changes += changeOptionDg!bool(mUptodateWithSameTime.isChecked(),
(b) => node.SetUptodateWithSameTime(cfgname, b), refnode.GetUptodateWithSameTime(cfgname));
enableControls(tool);
return changes;
}
bool mInitPerConfig;
CheckBox mPerConfig;
ComboBox mTool;
MultiLineText mCustomCmd;
Text mAddOpt;
Text mDependencies;
Text mOutFile;
CheckBox mLinkOut;
CheckBox mUptodateWithSameTime;
}
///////////////////////////////////////////////////////////////////////////////
class DirPropertyPage : GlobalPropertyPage
{
enum ID_BROWSEINSTALLDIR = 1000;
enum ID_IMPORTDIR = 1001;
enum ID_EXEPATH32 = 1002;
enum ID_EXEPATH64 = 1003;
enum ID_EXEPATH32COFF = 1004;
enum ID_LIBPATH32 = 1005;
enum ID_LIBPATH64 = 1006;
enum ID_LIBPATH32COFF = 1007;
enum ID_LINKER64 = 1008;
enum ID_LINKER32COFF = 1009;
this(GlobalOptions options)
{
super(options);
kNeededLines = 13;
}
void addBrowseDir(MultiLineText ctrl, string title)
{
addBrowsePath(ctrl, true, null, "\n", title);
}
extern(D) override void OnCommand(Widget w, int cmd)
{
switch(cmd)
{
case ID_BROWSEINSTALLDIR:
if(auto dir = browseDirectory(mCanvas.hwnd, "Select installation directory"))
mDmdPath.setText(dir);
break;
case ID_IMPORTDIR:
addBrowseDir(mImpPath, "Add import directory");
break;
case ID_EXEPATH32:
addBrowseDir(mExePath, "Add executable directory");
break;
case ID_EXEPATH64:
addBrowseDir(mExePath64, "Add executable directory");
break;
case ID_EXEPATH32COFF:
addBrowseDir(mExePath32coff, "Add executable directory");
break;
case ID_LIBPATH32:
addBrowseDir(mLibPath, "Add library directory");
break;
case ID_LIBPATH64:
addBrowseDir(mLibPath64, "Add library directory");
break;
case ID_LIBPATH32COFF:
addBrowseDir(mLibPath32coff, "Add library directory");
break;
case ID_LINKER64:
if(auto file = browseFile(mCanvas.hwnd, "Select linker executable", "Executables\0*.exe\0All Files\0*.*\0"))
mLinkerExecutable64.setText(file);
break;
case ID_LINKER32COFF:
if(auto file = browseFile(mCanvas.hwnd, "Select linker executable", "Executables\0*.exe\0All Files\0*.*\0"))
mLinkerExecutable32coff.setText(file);
break;
default:
break;
}
super.OnCommand(w, cmd);
}
void dirCreateControls(string name, string overrideIni)
{
auto btn = new Button(mCanvas, "...", ID_BROWSEINSTALLDIR);
AddControl(name ~ " install path", mDmdPath = new Text(mCanvas), btn);
mLinesPerMultiLine = 2;
btn = new Button(mCanvas, "+", ID_IMPORTDIR);
AddControl("Import paths", mImpPath = new MultiLineText(mCanvas), btn, 300);
mLinesPerMultiLine = 10;
string[] archs = ["Win32", "x64"];
if(overrideIni.length)
archs ~= "Win32-COFF";
AddControl("", mTabArch = new TabControl(mCanvas, archs), 700);
auto page32 = mTabArch.pages[0];
if(auto w = cast(Window)page32)
w.commandDelegate = mCanvas.commandDelegate;
mLineY = 0;
mAttachY = 0;
mLinesPerMultiLine = 3;
btn = new Button(page32, "+", ID_EXEPATH32);
AddControl("Executable paths", mExePath = new MultiLineText(page32), btn, 500);
mLinesPerMultiLine = 2;
btn = new Button(page32, "+", ID_LIBPATH32);
AddControl("Library paths", mLibPath = new MultiLineText(page32), btn, 500);
AddControl("Disassemble Command", mDisasmCommand = new Text(page32));
auto page64 = mTabArch.pages[1];
if(auto w = cast(Window)page64)
w.commandDelegate = mCanvas.commandDelegate;
mLineY = 0;
mAttachY = 0;
mLinesPerMultiLine = 3;
btn = new Button(page64, "+", ID_EXEPATH64);
AddControl("Executable paths", mExePath64 = new MultiLineText(page64), btn, 500);
mLinesPerMultiLine = 2;
btn = new Button(page64, "+", ID_LIBPATH64);
AddControl("Library paths", mLibPath64 = new MultiLineText(page64), btn, 500);
AddControl("Disassemble Command", mDisasmCommand64 = new Text(page64));
if(overrideIni.length)
{
AddControl("", mOverrideIni64 = new CheckBox(page64, overrideIni));
btn = new Button(page64, "...", ID_LINKER64);
AddControl("Linker", mLinkerExecutable64 = new Text(page64), btn);
AddControl("Additional options", mLinkerOptions64 = new Text(page64));
auto page32coff = mTabArch.pages[2];
if(auto w = cast(Window)page32coff)
w.commandDelegate = mCanvas.commandDelegate;
mLineY = 0;
mAttachY = 0;
mLinesPerMultiLine = 3;
btn = new Button(page32coff, "+", ID_EXEPATH32COFF);
AddControl("Executable paths", mExePath32coff = new MultiLineText(page32coff), btn, 500);
mLinesPerMultiLine = 2;
btn = new Button(page32coff, "+", ID_LIBPATH32COFF);
AddControl("Library paths", mLibPath32coff = new MultiLineText(page32coff), btn, 500);
AddControl("Disassemble Command", mDisasmCommand32coff = new Text(page32coff));
AddControl("", mOverrideIni32coff = new CheckBox(page32coff, overrideIni));
btn = new Button(page32coff, "...", ID_LINKER32COFF);
AddControl("Linker", mLinkerExecutable32coff = new Text(page32coff), btn);
AddControl("Additional options", mLinkerOptions32coff = new Text(page32coff));
}
}
override void UpdateDirty(bool bDirty)
{
super.UpdateDirty(bDirty);
enableControls();
}
void enableControls()
{
if(mOverrideIni64)
{
mLinkerExecutable64.setEnabled(mOverrideIni64.isChecked());
mLinkerOptions64.setEnabled(mOverrideIni64.isChecked());
}
if(mOverrideIni32coff)
{
mLinkerExecutable32coff.setEnabled(mOverrideIni32coff.isChecked());
mLinkerOptions32coff.setEnabled(mOverrideIni32coff.isChecked());
}
}
abstract CompilerDirectories* getCompilerOptions(GlobalOptions opts);
override void SetControls(GlobalOptions opts)
{
CompilerDirectories* opt = getCompilerOptions(opts);
mDmdPath.setText(opt.InstallDir);
mExePath.setText(opt.ExeSearchPath);
mImpPath.setText(opt.ImpSearchPath);
mLibPath.setText(opt.LibSearchPath);
mDisasmCommand.setText(opt.DisasmCommand);
mExePath64.setText(opt.ExeSearchPath64);
mLibPath64.setText(opt.LibSearchPath64);
mDisasmCommand64.setText(opt.DisasmCommand64);
if(mOverrideIni64)
{
mOverrideIni64.setChecked(opt.overrideIni64);
mLinkerExecutable64.setText(opt.overrideLinker64);
mLinkerOptions64.setText(opt.overrideOptions64);
}
if(mOverrideIni32coff)
{
mExePath32coff.setText(opt.ExeSearchPath32coff);
mLibPath32coff.setText(opt.LibSearchPath32coff);
mOverrideIni32coff.setChecked(opt.overrideIni32coff);
mLinkerExecutable32coff.setText(opt.overrideLinker32coff);
mLinkerOptions32coff.setText(opt.overrideOptions32coff);
mDisasmCommand32coff.setText(opt.DisasmCommand32coff);
}
enableControls();
}
override int DoApply(GlobalOptions opts, GlobalOptions refopts)
{
CompilerDirectories* opt = getCompilerOptions(opts);
CompilerDirectories* refopt = getCompilerOptions(refopts);
int changes = 0;
changes += changeOption(mDmdPath.getText(), opt.InstallDir, refopt.InstallDir);
changes += changeOption(mExePath.getText(), opt.ExeSearchPath, refopt.ExeSearchPath);
changes += changeOption(mImpPath.getText(), opt.ImpSearchPath, refopt.ImpSearchPath);
changes += changeOption(mLibPath.getText(), opt.LibSearchPath, refopt.LibSearchPath);
changes += changeOption(mDisasmCommand.getText(), opt.DisasmCommand, refopt.DisasmCommand);
changes += changeOption(mExePath64.getText(), opt.ExeSearchPath64, refopt.ExeSearchPath64);
changes += changeOption(mLibPath64.getText(), opt.LibSearchPath64, refopt.LibSearchPath64);
changes += changeOption(mDisasmCommand64.getText(), opt.DisasmCommand64, refopt.DisasmCommand64);
if(mOverrideIni64)
{
changes += changeOption(mOverrideIni64.isChecked(), opt.overrideIni64, refopt.overrideIni64);
changes += changeOption(mLinkerExecutable64.getText(), opt.overrideLinker64, refopt.overrideLinker64);
changes += changeOption(mLinkerOptions64.getText(), opt.overrideOptions64, refopt.overrideOptions64);
}
if(mOverrideIni32coff)
{
changes += changeOption(mExePath32coff.getText(), opt.ExeSearchPath32coff, refopt.ExeSearchPath32coff);
changes += changeOption(mLibPath32coff.getText(), opt.LibSearchPath32coff, refopt.LibSearchPath32coff);
changes += changeOption(mOverrideIni32coff.isChecked(), opt.overrideIni32coff, refopt.overrideIni32coff);
changes += changeOption(mLinkerExecutable32coff.getText(), opt.overrideLinker32coff, refopt.overrideLinker32coff);
changes += changeOption(mLinkerOptions32coff.getText(), opt.overrideOptions32coff, refopt.overrideOptions32coff);
changes += changeOption(mDisasmCommand32coff.getText(), opt.DisasmCommand32coff, refopt.DisasmCommand32coff);
}
return changes;
}
TabControl mTabArch;
Text mDmdPath;
MultiLineText mExePath;
MultiLineText mImpPath;
MultiLineText mLibPath;
Text mDisasmCommand;
MultiLineText mExePath64;
MultiLineText mLibPath64;
CheckBox mOverrideIni64;
Text mLinkerExecutable64;
Text mLinkerOptions64;
Text mDisasmCommand64;
MultiLineText mExePath32coff;
MultiLineText mLibPath32coff;
CheckBox mOverrideIni32coff;
Text mLinkerExecutable32coff;
Text mLinkerOptions32coff;
Text mDisasmCommand32coff;
}
///////////////////////////////////////////////////////////////////////////////
class DmdDirPropertyPage : DirPropertyPage
{
override string GetCategoryName() { return "D Options"; }
override string GetPageName() { return "DMD Directories"; }
this(GlobalOptions options)
{
super(options);
}
override void CreateControls()
{
dirCreateControls("DMD", "override linker settings from dmd configuration in sc.ini.");
}
override CompilerDirectories* getCompilerOptions(GlobalOptions opts)
{
return &opts.DMD;
}
}
///////////////////////////////////////////////////////////////////////////////
class GdcDirPropertyPage : DirPropertyPage
{
override string GetCategoryName() { return "D Options"; }
override string GetPageName() { return "GDC Directories"; }
this(GlobalOptions options)
{
super(options);
}
override void CreateControls()
{
dirCreateControls("GDC", "");
}
override CompilerDirectories* getCompilerOptions(GlobalOptions opts)
{
return &opts.GDC;
}
}
///////////////////////////////////////////////////////////////////////////////
class LdcDirPropertyPage : DirPropertyPage
{
override string GetCategoryName() { return "D Options"; }
override string GetPageName() { return "LDC Directories"; }
this(GlobalOptions options)
{
super(options);
}
override void CreateControls()
{
dirCreateControls("LDC", "");
}
override CompilerDirectories* getCompilerOptions(GlobalOptions opts)
{
return &opts.LDC;
}
}
///////////////////////////////////////////////////////////////////////////////
class ToolsProperty2Page : GlobalPropertyPage
{
override string GetCategoryName() { return "Projects"; }
override string GetPageName() { return "D Options"; }
this(GlobalOptions options)
{
super(options);
kNeededLines = 14;
}
override void CreateControls()
{
AddControl("", mElasticSpace = new CheckBox(mCanvas, "Use Elastic Space"));
AddControl("", mSortProjects = new CheckBox(mCanvas, "Sort project items"));
AddControl("", mShowUptodate = new CheckBox(mCanvas, "Show why a target is rebuilt"));
AddControl("", mTimeBuilds = new CheckBox(mCanvas, "Show build time"));
static if(enableShowMemUsage)
AddControl("", mShowMemUsage = new CheckBox(mCanvas, "Show compiler memory usage"));
AddControl("", mStopSlnBuild = new CheckBox(mCanvas, "Stop solution build on error"));
AddHorizontalLine();
AddControl("", mDemangleError = new CheckBox(mCanvas, "Demangle names in link errors/disassembly"));
AddControl("", mOptlinkDeps = new CheckBox(mCanvas, "Monitor linker dependencies"));
mLinesPerMultiLine = 2;
AddControl("Exclude Files/Folders", mExcludeFileDeps = new MultiLineText(mCanvas));
AddHorizontalLine();
//AddControl("Remove project item", mDeleteFiles =
// new ComboBox(mCanvas, [ "Do not delete file on disk", "Ask", "Delete file on disk" ]));
mLinesPerMultiLine = 2;
AddControl("JSON paths", mJSNPath = new MultiLineText(mCanvas));
AddControl("Resource includes", mIncPath = new Text(mCanvas));
AddHorizontalLine();
AddControl("Compile+Run options", mCompileAndRunOpts = new Text(mCanvas));
AddControl("Compile+Debug options", mCompileAndDbgOpts = new Text(mCanvas));
AddControl(" Debugger", mCompileAndDbgEngine = new ComboBox(mCanvas, [ "Visual Studio", "Mago", "Visual Studio (x86 Mixed Mode)" ], false));
}
override void SetControls(GlobalOptions opts)
{
mTimeBuilds.setChecked(opts.timeBuilds);
mElasticSpace.setChecked(opts.elasticSpace);
mSortProjects.setChecked(opts.sortProjects);
mShowUptodate.setChecked(opts.showUptodateFailure);
mStopSlnBuild.setChecked(opts.stopSolutionBuild);
mDemangleError.setChecked(opts.demangleError);
mOptlinkDeps.setChecked(opts.optlinkDeps);
mExcludeFileDeps.setText(opts.excludeFileDeps);
static if(enableShowMemUsage)
mShowMemUsage.setChecked(opts.showMemUsage);
//mDeleteFiles.setSelection(opts.deleteFiles + 1);
mIncPath.setText(opts.IncSearchPath);
mJSNPath.setText(opts.JSNSearchPath);
mCompileAndRunOpts.setText(opts.compileAndRunOpts);
mCompileAndDbgOpts.setText(opts.compileAndDbgOpts);
mCompileAndDbgEngine.setSelection(opts.compileAndDbgEngine);
}
override int DoApply(GlobalOptions opts, GlobalOptions refopts)
{
int changes = 0;
changes += changeOption(mTimeBuilds.isChecked(), opts.timeBuilds, refopts.timeBuilds);
changes += changeOption(mElasticSpace.isChecked(), opts.elasticSpace, refopts.elasticSpace);
changes += changeOption(mSortProjects.isChecked(), opts.sortProjects, refopts.sortProjects);
changes += changeOption(mShowUptodate.isChecked(), opts.showUptodateFailure, refopts.showUptodateFailure);
changes += changeOption(mStopSlnBuild.isChecked(), opts.stopSolutionBuild, refopts.stopSolutionBuild);
changes += changeOption(mDemangleError.isChecked(), opts.demangleError, refopts.demangleError);
changes += changeOption(mOptlinkDeps.isChecked(), opts.optlinkDeps, refopts.optlinkDeps);
changes += changeOption(mExcludeFileDeps.getText(), opts.excludeFileDeps, refopts.excludeFileDeps);
static if(enableShowMemUsage)
changes += changeOption(mShowMemUsage.isChecked(), opts.showMemUsage, refopts.showMemUsage);
//changes += changeOption(cast(byte) (mDeleteFiles.getSelection() - 1), opts.deleteFiles, refopts.deleteFiles);
changes += changeOption(mIncPath.getText(), opts.IncSearchPath, refopts.IncSearchPath);
changes += changeOption(mJSNPath.getText(), opts.JSNSearchPath, refopts.JSNSearchPath);
changes += changeOption(mCompileAndRunOpts.getText(), opts.compileAndRunOpts, refopts.compileAndRunOpts);
changes += changeOption(mCompileAndDbgOpts.getText(), opts.compileAndDbgOpts, refopts.compileAndDbgOpts);
changes += changeOption(mCompileAndDbgEngine.getSelection(), opts.compileAndDbgEngine, refopts.compileAndDbgEngine);
return changes;
}
CheckBox mTimeBuilds;
CheckBox mElasticSpace;
CheckBox mSortProjects;
CheckBox mShowUptodate;
CheckBox mStopSlnBuild;
CheckBox mDemangleError;
CheckBox mOptlinkDeps;
MultiLineText mExcludeFileDeps;
static if(enableShowMemUsage)
CheckBox mShowMemUsage;
//ComboBox mDeleteFiles;
Text mIncPath;
Text mCompileAndRunOpts;
Text mCompileAndDbgOpts;
ComboBox mCompileAndDbgEngine;
MultiLineText mJSNPath;
}
///////////////////////////////////////////////////////////////////////////////
class ColorizerPropertyPage : GlobalPropertyPage
{
override string GetCategoryName() { return "Language"; }
override string GetPageName() { return "Colorizer"; }
this(GlobalOptions options)
{
super(options);
kNeededLines = 11;
}
override void CreateControls()
{
AddControl("", mColorizeVersions = new CheckBox(mCanvas, "Colorize version and debug statements"));
AddControl("Colored types", mUserTypes = new MultiLineText(mCanvas), 1000);
AddHorizontalLine();
AddControl("", mColorizeCoverage = new CheckBox(mCanvas, "Colorize coverage from .LST file"));
AddControl("", mShowCoverageMargin = new CheckBox(mCanvas, "Show coverage margin"));
AddHorizontalLine();
AddControl("", mAutoOutlining = new CheckBox(mCanvas, "Add outlining regions when opening D files"));
AddControl("", mParseSource = new CheckBox(mCanvas, "Parse source for syntax errors"));
AddControl("", mPasteIndent = new CheckBox(mCanvas, "Reindent new lines after paste"));
}
override void SetControls(GlobalOptions opts)
{
mColorizeVersions.setChecked(opts.ColorizeVersions);
mColorizeCoverage.setChecked(opts.ColorizeCoverage);
mShowCoverageMargin.setChecked(opts.showCoverageMargin);
mAutoOutlining.setChecked(opts.autoOutlining);
mParseSource.setChecked(opts.parseSource);
mPasteIndent.setChecked(opts.pasteIndent);
mUserTypes.setText(opts.UserTypesSpec);
//mSemantics.setEnabled(false);
}
override int DoApply(GlobalOptions opts, GlobalOptions refopts)
{
int changes = 0;
changes += changeOption(mColorizeVersions.isChecked(), opts.ColorizeVersions, refopts.ColorizeVersions);
changes += changeOption(mColorizeCoverage.isChecked(), opts.ColorizeCoverage, refopts.ColorizeCoverage);
changes += changeOption(mShowCoverageMargin.isChecked(), opts.showCoverageMargin, refopts.showCoverageMargin);
changes += changeOption(mAutoOutlining.isChecked(), opts.autoOutlining, refopts.autoOutlining);
changes += changeOption(mParseSource.isChecked(), opts.parseSource, refopts.parseSource);
changes += changeOption(mPasteIndent.isChecked(), opts.pasteIndent, refopts.pasteIndent);
changes += changeOption(mUserTypes.getText(), opts.UserTypesSpec, refopts.UserTypesSpec);
return changes;
}
CheckBox mColorizeVersions;
CheckBox mColorizeCoverage;
CheckBox mShowCoverageMargin;
CheckBox mAutoOutlining;
CheckBox mParseSource;
CheckBox mPasteIndent;
MultiLineText mUserTypes;
}
///////////////////////////////////////////////////////////////////////////////
class IntellisensePropertyPage : GlobalPropertyPage
{
override string GetCategoryName() { return "Language"; }
override string GetPageName() { return "Intellisense"; }
this(GlobalOptions options)
{
super(options);
}
override void CreateControls()
{
AddControl("", mExpandSemantics = new CheckBox(mCanvas, "Expansions from semantic analysis"));
AddControl("", mExpandFromBuffer = new CheckBox(mCanvas, "Expansions from text buffer"));
AddControl("", mExpandFromJSON = new CheckBox(mCanvas, "Expansions from JSON browse information"));
AddControl("Show expansion when", mExpandTrigger = new ComboBox(mCanvas, [ "pressing Ctrl+Space", "writing '.'", "writing an identifier" ], false));
AddControl("", mShowTypeInTooltip = new CheckBox(mCanvas, "Show type of expressions in tool tip"));
AddControl("", mSemanticGotoDef = new CheckBox(mCanvas, "Use semantic analysis for \"Goto Definition\" (before trying JSON info)"));
version(DParserOption) AddControl("", mUseDParser = new CheckBox(mCanvas, "Use Alexander Bothe's D parsing engine for semantic analysis"));
AddControl("", mMixinAnalysis = new CheckBox(mCanvas, "Enable mixin analysis"));
AddControl("", mUFCSExpansions = new CheckBox(mCanvas, "Enable UFCS expansions"));
AddControl("Sort expansions", mSortExpMode = new ComboBox(mCanvas, [ "alphabetically", "by type", "by declaration and scope" ], false));
AddControl("", mExactExpMatch = new CheckBox(mCanvas, "Expansions match exact start instead of case insensitive sub string"));
}
override void UpdateDirty(bool bDirty)
{
super.UpdateDirty(bDirty);
EnableControls();
}
void EnableControls()
{
version(DParserOption) bool useDParser = mUseDParser.isChecked();
else bool useDParser = true;
mMixinAnalysis.setEnabled(useDParser);
mUFCSExpansions.setEnabled(useDParser);
mSortExpMode.setEnabled(useDParser);
}
override void SetControls(GlobalOptions opts)
{
mExpandSemantics.setChecked(opts.expandFromSemantics);
mExpandFromBuffer.setChecked(opts.expandFromBuffer);
mExpandFromJSON.setChecked(opts.expandFromJSON);
mExpandTrigger.setSelection(opts.expandTrigger);
mShowTypeInTooltip.setChecked(opts.showTypeInTooltip);
mSemanticGotoDef.setChecked(opts.semanticGotoDef);
version(DParserOption) mUseDParser.setChecked(opts.useDParser);
mMixinAnalysis.setChecked(opts.mixinAnalysis);
mUFCSExpansions.setChecked(opts.UFCSExpansions);
mSortExpMode.setSelection(opts.sortExpMode);
mExactExpMatch.setChecked(opts.exactExpMatch);
//mExpandSemantics.setEnabled(false);
}
override int DoApply(GlobalOptions opts, GlobalOptions refopts)
{
int changes = 0;
changes += changeOption(mExpandSemantics.isChecked(), opts.expandFromSemantics, refopts.expandFromSemantics);
changes += changeOption(mExpandFromBuffer.isChecked(), opts.expandFromBuffer, refopts.expandFromBuffer);
changes += changeOption(mExpandFromJSON.isChecked(), opts.expandFromJSON, refopts.expandFromJSON);
changes += changeOption(cast(byte) mExpandTrigger.getSelection(), opts.expandTrigger, refopts.expandTrigger);
changes += changeOption(mShowTypeInTooltip.isChecked(), opts.showTypeInTooltip, refopts.showTypeInTooltip);
changes += changeOption(mSemanticGotoDef.isChecked(), opts.semanticGotoDef, refopts.semanticGotoDef);
version(DParserOption) changes += changeOption(mUseDParser.isChecked(), opts.useDParser, refopts.useDParser);
changes += changeOption(mMixinAnalysis.isChecked(), opts.mixinAnalysis, refopts.mixinAnalysis);
changes += changeOption(mUFCSExpansions.isChecked(), opts.UFCSExpansions, refopts.UFCSExpansions);
changes += changeOption(cast(ubyte) mSortExpMode.getSelection(), opts.sortExpMode, refopts.sortExpMode);
changes += changeOption(mExactExpMatch.isChecked(), opts.exactExpMatch, refopts.exactExpMatch);
return changes;
}
CheckBox mExpandSemantics;
CheckBox mExpandFromBuffer;
CheckBox mExpandFromJSON;
ComboBox mExpandTrigger;
CheckBox mShowTypeInTooltip;
CheckBox mSemanticGotoDef;
version(DParserOption) CheckBox mUseDParser;
CheckBox mUFCSExpansions;
ComboBox mSortExpMode;
CheckBox mExactExpMatch;
CheckBox mMixinAnalysis;
}
///////////////////////////////////////////////////////////////////////////////
struct MagoOptions
{
bool hideInternalNames;
bool showStaticsInAggr;
void saveToRegistry()
{
scope RegKey keyMago = new RegKey(HKEY_CURRENT_USER, "SOFTWARE\\MagoDebugger", true);
keyMago.Set("hideInternalNames", hideInternalNames);
keyMago.Set("showStaticsInAggr", showStaticsInAggr);
}
void loadFromRegistry()
{
scope RegKey keyMago = new RegKey(HKEY_CURRENT_USER, "SOFTWARE\\MagoDebugger", false);
hideInternalNames = (keyMago.GetDWORD("hideInternalNames", 0) != 0);
showStaticsInAggr = (keyMago.GetDWORD("showStaticsInAggr", 0) != 0);
}
}
class MagoPropertyPage : ResizablePropertyPage
{
override string GetCategoryName() { return "Debugging"; }
override string GetPageName() { return "Mago"; }
MagoOptions mOptions;
override void CreateControls()
{
AddLabel("Changes to these settings only apply to new debugging sessions");
AddControl("", mHideInternalNames = new CheckBox(mCanvas, "Hide compiler generated symbols"));
AddControl("", mShowStaticsInAggr = new CheckBox(mCanvas, "Show static fields in structs and classes"));
}
override void UpdateDirty(bool bDirty)
{
super.UpdateDirty(bDirty);
EnableControls();
}
override void UpdateControls()
{
SetControls();
EnableControls();
}
/*override*/ int IsPageDirty()
{
mixin(LogCallMix);
if(mWindow)
{
MagoOptions opt;
return DoApply(opt, mOptions) > 0 ? S_OK : S_FALSE;
}
return S_FALSE;
}
/*override*/ int Apply()
{
mixin(LogCallMix);
DoApply(mOptions, mOptions);
mOptions.saveToRegistry();
return S_OK;
}
void EnableControls()
{
}
void SetControls()
{
mOptions.loadFromRegistry();
mHideInternalNames.setChecked(mOptions.hideInternalNames);
mShowStaticsInAggr.setChecked(mOptions.showStaticsInAggr);
}
int DoApply(ref MagoOptions opts, ref MagoOptions refopts)
{
int changes = 0;
changes += changeOption(mHideInternalNames.isChecked(), opts.hideInternalNames, refopts.hideInternalNames);
changes += changeOption(mShowStaticsInAggr.isChecked(), opts.showStaticsInAggr, refopts.showStaticsInAggr);
return changes;
}
CheckBox mHideInternalNames;
CheckBox mShowStaticsInAggr;
}
///////////////////////////////////////////////////////////////////////////////
// more guids in dpackage.d starting up to 980f
const GUID g_GeneralPropertyPage = uuid("002a2de9-8bb6-484d-9810-7e4ad4084715");
const GUID g_DmdGeneralPropertyPage = uuid("002a2de9-8bb6-484d-9811-7e4ad4084715");
const GUID g_DmdDebugPropertyPage = uuid("002a2de9-8bb6-484d-9812-7e4ad4084715");
const GUID g_DmdCodeGenPropertyPage = uuid("002a2de9-8bb6-484d-9813-7e4ad4084715");
const GUID g_DmdMessagesPropertyPage = uuid("002a2de9-8bb6-484d-9814-7e4ad4084715");
const GUID g_DmdOutputPropertyPage = uuid("002a2de9-8bb6-484d-9815-7e4ad4084715");
const GUID g_DmdLinkerPropertyPage = uuid("002a2de9-8bb6-484d-9816-7e4ad4084715");
const GUID g_DmdEventsPropertyPage = uuid("002a2de9-8bb6-484d-9817-7e4ad4084715");
const GUID g_CommonPropertyPage = uuid("002a2de9-8bb6-484d-9818-7e4ad4084715");
const GUID g_DebuggingPropertyPage = uuid("002a2de9-8bb6-484d-9819-7e4ad4084715");
const GUID g_FilePropertyPage = uuid("002a2de9-8bb6-484d-981a-7e4ad4084715");
const GUID g_DmdDocPropertyPage = uuid("002a2de9-8bb6-484d-981b-7e4ad4084715");
const GUID g_DmdCmdLinePropertyPage = uuid("002a2de9-8bb6-484d-981c-7e4ad4084715");
// does not need to be registered, created explicitely by package
const GUID g_DmdDirPropertyPage = uuid("002a2de9-8bb6-484d-9820-7e4ad4084715");
const GUID g_GdcDirPropertyPage = uuid("002a2de9-8bb6-484d-9824-7e4ad4084715");
const GUID g_LdcDirPropertyPage = uuid("002a2de9-8bb6-484d-9825-7e4ad4084715");
const GUID g_ToolsProperty2Page = uuid("002a2de9-8bb6-484d-9822-7e4ad4084715");
// registered under Languages\\Language Services\\D\\EditorToolsOptions\\Colorizer, created explicitely by package
const GUID g_ColorizerPropertyPage = uuid("002a2de9-8bb6-484d-9821-7e4ad4084715");
const GUID g_IntellisensePropertyPage = uuid("002a2de9-8bb6-484d-9823-7e4ad4084715");
const GUID g_MagoPropertyPage = uuid("002a2de9-8bb6-484d-9826-7e4ad4084715");
const GUID*[] guids_propertyPages =
[
&g_GeneralPropertyPage,
&g_DmdGeneralPropertyPage,
&g_DmdDebugPropertyPage,
&g_DmdCodeGenPropertyPage,
&g_DmdMessagesPropertyPage,
&g_DmdOutputPropertyPage,
&g_DmdLinkerPropertyPage,
&g_DmdEventsPropertyPage,
&g_CommonPropertyPage,
&g_DebuggingPropertyPage,
&g_FilePropertyPage,
&g_DmdDocPropertyPage,
&g_DmdCmdLinePropertyPage,
];
class PropertyPageFactory : DComObject, IClassFactory
{
static PropertyPageFactory create(CLSID* rclsid)
{
foreach(id; guids_propertyPages)
if(*id == *rclsid)
return newCom!PropertyPageFactory(rclsid);
return null;
}
this(CLSID* rclsid)
{
mClsid = *rclsid;
}
override HRESULT QueryInterface(in IID* riid, void** pvObject)
{
if(queryInterface2!(IClassFactory) (this, IID_IClassFactory, riid, pvObject))
return S_OK;
return super.QueryInterface(riid, pvObject);
}
override HRESULT CreateInstance(IUnknown UnkOuter, in IID* riid, void** pvObject)
{
PropertyPage ppp;
assert(!UnkOuter);
if(mClsid == g_GeneralPropertyPage)
ppp = newCom!GeneralPropertyPage();
else if(mClsid == g_DebuggingPropertyPage)
ppp = newCom!DebuggingPropertyPage();
else if(mClsid == g_DmdGeneralPropertyPage)
ppp = newCom!DmdGeneralPropertyPage();
else if(mClsid == g_DmdDebugPropertyPage)
ppp = newCom!DmdDebugPropertyPage();
else if(mClsid == g_DmdCodeGenPropertyPage)
ppp = newCom!DmdCodeGenPropertyPage();
else if(mClsid == g_DmdMessagesPropertyPage)
ppp = newCom!DmdMessagesPropertyPage();
else if(mClsid == g_DmdDocPropertyPage)
ppp = newCom!DmdDocPropertyPage();
else if(mClsid == g_DmdOutputPropertyPage)
ppp = newCom!DmdOutputPropertyPage();
else if(mClsid == g_DmdLinkerPropertyPage)
ppp = newCom!DmdLinkerPropertyPage();
else if(mClsid == g_DmdEventsPropertyPage)
ppp = newCom!DmdEventsPropertyPage();
else if(mClsid == g_DmdCmdLinePropertyPage)
ppp = newCom!DmdCmdLinePropertyPage();
else if(mClsid == g_CommonPropertyPage)
ppp = newCom!CommonPropertyPage();
else if(mClsid == g_FilePropertyPage)
ppp = newCom!FilePropertyPage();
else
return E_INVALIDARG;
return ppp.QueryInterface(riid, pvObject);
}
override HRESULT LockServer(in BOOL fLock)
{
return S_OK;
}
static int GetProjectPages(CAUUID *pPages, bool addFile)
{
version(all) {
pPages.cElems = (addFile ? 12 : 11);
pPages.pElems = cast(GUID*)CoTaskMemAlloc(pPages.cElems*GUID.sizeof);
if (!pPages.pElems)
return E_OUTOFMEMORY;
int idx = 0;
if(addFile)
pPages.pElems[idx++] = g_FilePropertyPage;
pPages.pElems[idx++] = g_GeneralPropertyPage;
pPages.pElems[idx++] = g_DebuggingPropertyPage;
pPages.pElems[idx++] = g_DmdGeneralPropertyPage;
pPages.pElems[idx++] = g_DmdDebugPropertyPage;
pPages.pElems[idx++] = g_DmdCodeGenPropertyPage;
pPages.pElems[idx++] = g_DmdMessagesPropertyPage;
pPages.pElems[idx++] = g_DmdDocPropertyPage;
pPages.pElems[idx++] = g_DmdOutputPropertyPage;
pPages.pElems[idx++] = g_DmdLinkerPropertyPage;
pPages.pElems[idx++] = g_DmdCmdLinePropertyPage;
pPages.pElems[idx++] = g_DmdEventsPropertyPage;
return S_OK;
} else {
return returnError(E_NOTIMPL);
}
}
static int GetCommonPages(CAUUID *pPages)
{
pPages.cElems = 1;
pPages.pElems = cast(GUID*)CoTaskMemAlloc(pPages.cElems*GUID.sizeof);
if (!pPages.pElems)
return E_OUTOFMEMORY;
pPages.pElems[0] = g_CommonPropertyPage;
return S_OK;
}
static int GetFilePages(CAUUID *pPages)
{
pPages.cElems = 1;
pPages.pElems = cast(GUID*)CoTaskMemAlloc(pPages.cElems*GUID.sizeof);
if (!pPages.pElems)
return E_OUTOFMEMORY;
pPages.pElems[0] = g_FilePropertyPage;
return S_OK;
}
private:
GUID mClsid;
}