ide: New FillDiff features

git-svn-id: svn://ultimatepp.org/upp/trunk@6948 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2014-02-24 19:06:00 +00:00
parent a2a391f4e3
commit 3024f7af94
16 changed files with 389 additions and 160 deletions

View file

@ -289,4 +289,28 @@ void MemoryProfileInfo() {
PromptOK("[C " + DeQtfLf(text));
};
FileSelButton::FileSelButton(MODE mode, const char *title)
: title(title), mode(mode)
{
button.NoWantFocus();
button.SetImage(CtrlImg::right_arrow());
button <<= THISBACK(OnAction);
}
void FileSelButton::OnAction()
{
Ctrl *owner = button.GetParent();
ASSERT(owner);
String old = ~*owner;
if(mode == MODE_DIR)
ActiveDir(old);
else
Set(old);
if(mode == MODE_OPEN ? ExecuteOpen(title) : mode == MODE_SAVE ? ExecuteSaveAs(title) : ExecuteSelectDir(title))
{
*owner <<= Get();
owner->Action();
}
}
END_UPP_NAMESPACE

View file

@ -453,6 +453,31 @@ public:
void Set(const ValueMap& m);
};
class FileSelButton : public FileSel
{
public:
typedef FileSelButton CLASSNAME;
enum MODE { MODE_OPEN, MODE_SAVE, MODE_DIR };
FileSelButton(MODE mode = MODE_OPEN, const char *title = NULL);
void Attach(Ctrl& parent) { parent.AddFrame(button); }
void Title(String t) { title = t; }
String GetTitle() const { return title; }
private:
void OnAction();
private:
FrameRight<Button> button;
String title;
MODE mode;
};
struct OpenFileButton : FileSelButton { OpenFileButton(const char *title = NULL) : FileSelButton(MODE_OPEN, title) {} };
struct SaveFileButton : FileSelButton { SaveFileButton(const char *title = NULL) : FileSelButton(MODE_SAVE, title) {} };
struct SelectDirButton : FileSelButton { SelectDirButton(const char *title = NULL) : FileSelButton(MODE_DIR, title) {} };
void Set(ArrayCtrl& array, int ii, IdCtrls& m);
void Get(ArrayCtrl& array, int ii, IdCtrls& m);

View file

@ -1,9 +1,15 @@
PREMULTIPLIED
IMAGE_ID(Diff)
IMAGE_ID(DirDiff)
IMAGE_BEGIN_DATA
IMAGE_DATA(120,156,99,16,96,16,96,24,68,224,63,126,220,64,0,51,252,127,240,224,1,86,12,211,223,59,97,63,86,76,11,253)
IMAGE_DATA(200,124,100,253,32,54,33,253,216,204,66,182,31,221,12,100,253,132,195,17,129,105,97,63,53,252,143,105,55,238,240,71)
IMAGE_DATA(164,13,76,253,32,177,3,7,14,224,212,15,18,223,186,243,35,78,247,131,244,226,210,15,211,139,172,159,194,244,59,160)
IMAGE_DATA(0,0,219,32,170,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
IMAGE_END_DATA(128, 1)
IMAGE_DATA(120,156,205,148,49,14,130,48,20,134,187,194,196,226,33,224,16,192,226,226,238,37,156,117,46,23,48,49,225,0,92,162)
IMAGE_DATA(14,46,148,217,83,16,111,224,9,158,62,16,105,105,95,145,8,209,151,252,1,90,190,191,125,229,15,44,96,1,251,163)
IMAGE_DATA(2,183,178,17,49,168,235,218,170,142,63,158,164,85,75,240,234,179,202,227,253,24,111,243,82,215,31,122,168,252,248,57)
IMAGE_DATA(246,90,98,253,57,250,55,215,166,207,191,207,134,201,227,88,85,85,36,143,227,231,203,157,220,63,178,20,223,177,42,255)
IMAGE_DATA(101,126,127,91,115,254,12,162,40,218,10,33,64,74,9,121,158,223,124,223,95,77,225,147,36,225,82,114,40,203,178,241)
IMAGE_DATA(232,36,196,1,208,123,140,79,211,148,3,236,1,128,105,186,94,25,224,220,243,21,244,128,215,149,224,185,193,75,249,230)
IMAGE_DATA(213,143,107,120,180,252,206,197,171,235,27,30,216,99,81,108,32,203,82,77,156,175,109,253,59,123,249,176,58,143,97,77)
IMAGE_DATA(9,38,197,27,251,10,195,80,203,135,231,121,84,62,172,189,197,113,76,230,3,189,29,30,205,21,243,69,229,3,231,28)
IMAGE_DATA(251,104,212,242,246,124,16,188,182,143,150,183,231,195,193,107,231,71,229,195,210,255,228,122,0,51,144,153,68,0,0,0)
IMAGE_END_DATA(288, 2)

View file

@ -4,7 +4,8 @@ namespace Upp {
#define IMAGECLASS DiffImg
#define IMAGEFILE <TextDiffCtrl/Diff.iml>
#include <Draw/iml.h>
#include <Draw/iml_source.h>
TextDiffCtrl::TextDiffCtrl()
{
left.Gutter(30);
@ -75,6 +76,8 @@ void TextDiffCtrl::Set(Stream& l, Stream& r)
}
if(firstdiff >= 0)
left.SetSb(max(firstdiff - 2, 0));
left.ClearSelection();
right.ClearSelection();
}
void TextDiffCtrl::Set(const String& l, const String& r)
@ -166,101 +169,4 @@ FileSel& DiffFs() {
return fs;
}
void PatchDiff::Copy(FileIn& in, FileIn& oin, int& l, int ln, int n)
{
if(ln < l)
throw CParser::Error("");
while(l < ln) {
if(oin.IsEof())
throw CParser::Error("");
extfile << oin.GetLine() << "\r\n";
l++;
}
l += n;
while(n--)
oin.GetLine();
}
void PatchDiff::LoadDiff(const char *fn)
{
try {
FileIn in(fn);
FileIn oin(editfile);
extfile.Clear();
int l = 1;
String s = in.GetLine();
if(IsDigit(*s)) {
in.Seek(0);
while(!in.IsEof()) {
s = in.GetLine();
if(IsDigit(*s)) {
CParser p(s);
int ln = p.ReadNumber();
int n = 0;
if(p.Char('a'))
ln++;
else {
n = p.Char(',') ? p.ReadNumber() - ln + 1 : 1;
if(!p.Char('c'))
p.PassChar('d');
}
Copy(in, oin, l, ln, n);
}
else
if(*s == '>') {
if(s[1] != ' ')
throw CParser::Error("");
extfile << s.Mid(2) << "\r\n";
}
else
if(*s != '<' && *s != '-')
throw CParser::Error("");
}
}
else {
for(;;) {
if(in.IsEof())
throw CParser::Error("");
if(in.GetLine().Mid(0, 4) == "+++ ")
break;
}
while(!in.IsEof()) {
String s = in.GetLine();
if(*s == '@') {
CParser p(s);
p.PassChar2('@', '@');
p.PassChar('-');
int ln = p.ReadNumber();
int n = 1;
if(p.Char(','))
n = p.ReadNumber();
Copy(in, oin, l, ln, n);
}
else
if(*s == '+' || *s == ' ')
extfile << s.Mid(1) << "\r\n";
else
if(*s != '-')
throw CParser::Error("");
}
}
while(!oin.IsEof())
extfile << oin.GetLine() << "\r\n";
}
catch(CParser::Error&) {
Exclamation("Invalid file format!");
extfile = LoadFile(fn);
}
}
void PatchDiff::Open()
{
if(!DiffFs().ExecuteOpen())
return;
String f = ~DiffFs();
r <<= f;
LoadDiff(f);
diff.Set(LoadFile(editfile), extfile);
}
};

View file

@ -0,0 +1,118 @@
#include "TextDiffCtrl.h"
namespace Upp {
void DirDiffDlg::GatherFilesDeep(Index<String>& files, const String& base, const String& path)
{
FindFile ff(AppendFileName(AppendFileName(base, path), "*.*"));
while(ff) {
String p = (path.GetCount() ? path + '/' : String()) + ff.GetName();
if(hidden || !ff.IsHidden()) {
if(ff.IsFile())
files.FindAdd(p);
else
if(ff.IsFolder())
GatherFilesDeep(files, base, p);
}
ff.Next();
}
}
bool FileEqual(const String& f1, const String& f2)
{
FileIn in1(f1);
FileIn in2(f2);
if(in1 && in2) {
while(!in1.IsEof() && !in2.IsEof()) {
String a = in1.Get(256 * 1024);
String b = in2.Get(256 * 1024);
if(a != b)
return false;
}
return true;
}
return false;
}
void DirDiffDlg::Compare()
{
Index<String> fs;
GatherFilesDeep(fs, ~dir1, Null);
GatherFilesDeep(fs, ~dir2, Null);
files.Clear();
Vector<String> f = fs.PickKeys();
Sort(f);
Progress pi(t_("Comparing.."));
pi.SetTotal(f.GetCount());
for(int i = 0; i < f.GetCount(); i++) {
if(pi.StepCanceled())
break;
String p1 = AppendFileName(~dir1, f[i]);
String p2 = AppendFileName(~dir2, f[i]);
if(!FileEqual(p1, p2))
files.Add(f[i], NativePathIcon(FileExists(p1) ? p1 : p2));
}
}
void DirDiffDlg::ClearFiles()
{
files.Clear();
compare.Enable(!IsNull(dir1) && !IsNull(dir2));
}
void DirDiffDlg::File()
{
String fn = files.GetCurrentName();
String p1 = AppendFileName(~dir1, fn);
String p2 = AppendFileName(~dir2, fn);
diff.Set(Null, Null);
if(GetFileLength(p1) < 4 * 1024 * 1024 && GetFileLength(p2) < 4 * 1024 * 1024)
diff.Set(LoadFile(p1), LoadFile(p2));
lfile <<= p1;
rfile <<= p2;
}
DirDiffDlg::DirDiffDlg()
{
int div = HorzLayoutZoom(4);
int cy = dir1.GetStdSize().cy;
int bcx = GetTextSize(t_("Compare"), StdFont()).cx * 12 / 10 + 2 * div;
hidden.SetLabel(t_("Hidden"));
compare.SetLabel(t_("Compare"));
int bcy = compare.GetStdSize().cy;
files_pane.Add(dir1.TopPos(0, cy).HSizePos());
files_pane.Add(dir2.TopPos(cy + div, cy).HSizePos());
files_pane.Add(hidden.TopPos(2 * cy + 2 * div, bcy).HSizePos(0, bcx));
files_pane.Add(compare.TopPos(2 * cy + 2 * div, bcy).RightPos(0, bcx));
files_pane.Add(files.VSizePos(2 * cy + bcy + 3 * div, 0).HSizePos());
Add(files_diff.SizePos());
files_diff.Set(files_pane, diff);
files_diff.SetPos(2000);
Sizeable().Zoomable();
seldir1.Attach(dir1);
seldir2.Attach(dir2);
compare <<= THISBACK(Compare);
dir1 <<= THISBACK(ClearFiles);
dir2 <<= THISBACK(ClearFiles);
files.WhenSel = THISBACK(File);
lfile.Height(EditField::GetStdHeight());
lfile.SetReadOnly();
diff.InsertFrameLeft(lfile);
rfile.Height(EditField::GetStdHeight());
rfile.SetReadOnly();
diff.InsertFrameRight(rfile);
Icon(DiffImg::Diff());
}
};

View file

@ -0,0 +1,102 @@
#include "TextDiffCtrl.h"
namespace Upp {
void PatchDiff::Copy(FileIn& in, FileIn& oin, int& l, int ln, int n)
{
if(ln < l)
throw CParser::Error("");
while(l < ln) {
if(oin.IsEof())
throw CParser::Error("");
extfile << oin.GetLine() << "\r\n";
l++;
}
l += n;
while(n--)
oin.GetLine();
}
void PatchDiff::LoadDiff(const char *fn)
{
try {
FileIn in(fn);
FileIn oin(editfile);
extfile.Clear();
int l = 1;
String s = in.GetLine();
if(IsDigit(*s)) {
in.Seek(0);
while(!in.IsEof()) {
s = in.GetLine();
if(IsDigit(*s)) {
CParser p(s);
int ln = p.ReadNumber();
int n = 0;
if(p.Char('a'))
ln++;
else {
n = p.Char(',') ? p.ReadNumber() - ln + 1 : 1;
if(!p.Char('c'))
p.PassChar('d');
}
Copy(in, oin, l, ln, n);
}
else
if(*s == '>') {
if(s[1] != ' ')
throw CParser::Error("");
extfile << s.Mid(2) << "\r\n";
}
else
if(*s != '<' && *s != '-')
throw CParser::Error("");
}
}
else {
for(;;) {
if(in.IsEof())
throw CParser::Error("");
if(in.GetLine().Mid(0, 4) == "+++ ")
break;
}
while(!in.IsEof()) {
String s = in.GetLine();
if(*s == '@') {
CParser p(s);
p.PassChar2('@', '@');
p.PassChar('-');
int ln = p.ReadNumber();
int n = 1;
if(p.Char(','))
n = p.ReadNumber();
Copy(in, oin, l, ln, n);
}
else
if(*s == '+' || *s == ' ')
extfile << s.Mid(1) << "\r\n";
else
if(*s != '-')
throw CParser::Error("");
}
}
while(!oin.IsEof())
extfile << oin.GetLine() << "\r\n";
}
catch(CParser::Error&) {
Exclamation("Invalid file format!");
extfile = LoadFile(fn);
}
}
void PatchDiff::Open()
{
if(!DiffFs().ExecuteOpen())
return;
String f = ~DiffFs();
r <<= f;
LoadDiff(f);
diff.Set(LoadFile(editfile), extfile);
}
};

View file

@ -22,6 +22,7 @@ TextCompareCtrl::TextCompareCtrl()
gutter_bg = Color(151, 190, 239);
gutter_fg = SGreen;
cursor = anchor = Null;
gutter_capture = false;
}
void TextCompareCtrl::DoSelection(int y, bool shift)
@ -43,24 +44,29 @@ void TextCompareCtrl::DoSelection(int y, bool shift)
void TextCompareCtrl::LeftDown(Point pt, dword keyflags)
{
Size sz = GetSize();
if(pt.x > sz.cx - gutter_width || HasCapture()) {
if(pt.x > sz.cx - gutter_width || HasCapture() && gutter_capture) {
if(!HasCapture())
SetCapture();
int line = (pt.y * lines.GetCount()) / sz.cy;
int page_lines = sz.cy / letter.cy;
scroll.SetY(line - page_lines / 2);
gutter_capture = true;
}
else {
DoSelection(pt.y, keyflags & K_SHIFT);
SetCapture();
gutter_capture = false;
}
SetWantFocus();
}
void TextCompareCtrl::MouseMove(Point pt, dword)
void TextCompareCtrl::MouseMove(Point pt, dword flags)
{
if(HasCapture())
DoSelection(pt.y, true);
if(gutter_capture)
LeftDown(pt, flags);
else
DoSelection(pt.y, true);
}
void TextCompareCtrl::LeftUp(Point pt, dword keyflags)
@ -92,7 +98,7 @@ void TextCompareCtrl::Copy()
void TextCompareCtrl::RightDown(Point p, dword keyflags)
{
MenuBar b;
b.Add(cursor != anchor, t_("Copy"), CtrlImg::copy(), THISBACK(Copy)).Key(K_CTRL_C);
b.Add(!IsNull(cursor), t_("Copy"), CtrlImg::copy(), THISBACK(Copy)).Key(K_CTRL_C);
b.Execute();
}
@ -210,7 +216,10 @@ void TextCompareCtrl::Paint(Draw& draw)
int y = i * letter.cy - offset.cy;
Color ink = l.color;
Color paper = SColorPaper();
if(!IsNull(l.number) && l.number >= sell && l.number <= selh) {
if(IsNull(l.number))
paper = SGray();
else
if(l.number >= sell && l.number <= selh) {
ink = SColorHighlightText;
paper = SColorHighlight;
}
@ -243,6 +252,11 @@ void TextCompareCtrl::SetFont(Font f, Font nf)
Layout();
}
void TextCompareCtrl::SetFont(Font f)
{
SetFont(f, GetNumberFont());
}
void TextCompareCtrl::Layout()
{
scroll.Set(scroll, (scroll.GetReducedViewSize() - Size(number_width + gutter_width, 0)) / letter, Size(maxwidth, lines.GetCount()));

View file

@ -5,6 +5,10 @@
namespace Upp {
#define IMAGECLASS DiffImg
#define IMAGEFILE <TextDiffCtrl/Diff.iml>
#include <Draw/iml_header.h>
class TextSection
{
public:
@ -68,6 +72,7 @@ private:
int gutter_width;
int cursor;
int anchor;
bool gutter_capture;
typedef TextCompareCtrl CLASSNAME;
@ -79,6 +84,7 @@ public:
int GetCount() const { return lines.GetCount(); }
void SetFont(Font f, Font nf);
void SetFont(Font f);
Font GetFont() const { return font; }
Font GetNumberFont() const { return number_font; }
@ -124,6 +130,8 @@ public:
void InsertFrameRight(CtrlFrame& f) { right.InsertFrame(0, f); }
void AddFrameLeft(CtrlFrame& f) { left.AddFrame(f); }
void AddFrameRight(CtrlFrame& f) { right.AddFrame(f); }
void SetFont(Font f, Font nf) { left.SetFont(f, nf); right.SetFont(f, nf); }
void SetFont(Font f) { left.SetFont(f); right.SetFont(f); }
TextDiffCtrl();
};
@ -137,7 +145,7 @@ struct DiffDlg : public TopWindow {
String extfile;
typedef DiffDlg CLASSNAME;
void Write();
void Execute(const String& f);
@ -168,6 +176,39 @@ struct PatchDiff : FileDiff {
void LoadDiff(const char *fn);
};
class DirDiffDlg : public TopWindow {
Splitter files_diff;
TextDiffCtrl diff;
ParentCtrl files_pane;
FileList files;
SelectDirButton seldir1;
WithDropChoice<EditString> dir1;
SelectDirButton seldir2;
WithDropChoice<EditString> dir2;
Option hidden;
Button compare;
FrameTop<EditString> lfile, rfile;
void GatherFilesDeep(Index<String>& files, const String& base, const String& path);
void Compare();
void ClearFiles();
void File();
public:
typedef DirDiffDlg CLASSNAME;
void SetFont(Font fnt) { diff.SetFont(fnt); }
void Dir1(const String& dir) { dir1 <<= dir; }
void Dir2(const String& dir) { dir2 <<= dir; }
void Dir1AddList(const String& dir) { dir1.AddList(dir); }
void Dir2AddList(const String& dir) { dir2.AddList(dir); }
DirDiffDlg();
};
};
#endif

View file

@ -6,5 +6,7 @@ file
TextDiff.cpp,
TextCtrl.cpp,
DiffCtrl.cpp,
PatchDiff.cpp,
DirDiff.cpp,
Diff.iml;

View file

@ -1,25 +0,0 @@
#include "ide.h"
FileSelButton::FileSelButton(MODE mode, const char *title)
: title(title), mode(mode)
{
button.NoWantFocus();
button.SetImage(CtrlImg::right_arrow());
button <<= THISBACK(OnAction);
}
void FileSelButton::OnAction()
{
Ctrl *owner = button.GetParent();
ASSERT(owner);
String old = ~*owner;
if(mode == MODE_DIR)
ActiveDir(old);
else
Set(old);
if(mode == MODE_OPEN ? ExecuteOpen(title) : mode == MODE_SAVE ? ExecuteSaveAs(title) : ExecuteSelectDir(title))
{
*owner <<= Get();
owner->Action();
}
}

View file

@ -130,3 +130,4 @@ void Ide::Xml()
dlg.Execute();
StoreToGlobal(dlg, "XMLview");
}

View file

@ -39,30 +39,6 @@ const char *FindTag(const char *txt, const char *tag);
const char *FindAfter(const char *txt, const char *tag);
int IdeLocateLine(String old_file, int old_line, String new_file);
class FileSelButton : public FileSel
{
public:
typedef FileSelButton CLASSNAME;
enum MODE { MODE_OPEN, MODE_SAVE, MODE_DIR };
FileSelButton(MODE mode = MODE_OPEN, const char *title = NULL);
void Attach(Ctrl& parent) { parent.AddFrame(button); }
void Title(String t) { title = t; }
String GetTitle() const { return title; }
private:
void OnAction();
private:
FrameRight<Button> button;
String title;
MODE mode;
};
struct OpenFileButton : FileSelButton { OpenFileButton(const char *title = NULL) : FileSelButton(MODE_OPEN, title) {} };
struct SaveFileButton : FileSelButton { SaveFileButton(const char *title = NULL) : FileSelButton(MODE_SAVE, title) {} };
struct SelectDirButton : FileSelButton { SelectDirButton(const char *title = NULL) : FileSelButton(MODE_DIR, title) {} };
#include "UppDlg.h"
void Puts(const char *s);
@ -975,6 +951,7 @@ public:
void Qtf();
void Xml();
void Json();
void DoDirDiff();
void ConsoleMenu(Bar& menu);

View file

@ -111,4 +111,5 @@ KEY(TOCSTRING, "Convert to C string", 0)
KEY(DIFF, "Compare with file..", 0)
KEY(SVNDIFF, "Show svn history of file..", 0)
KEY(PATCH, "Patch/diff..", 0)
KEY(PATCH, "Patch/diff..", 0)
KEY(DIRDIFF, "Compare directories..", 0)

View file

@ -61,7 +61,6 @@ file
idewin.cpp,
About.cpp,
Help.cpp,
Util.cpp,
Macro.cpp,
Calc.cpp,
FormatCode.cpp,

View file

@ -541,6 +541,7 @@ void Ide::BrowseMenu(Bar& menu) {
menu.AddMenu(AK_QTF, IdeCommonImg::Qtf(), THISBACK(Qtf));
menu.AddMenu(!designer, AK_XML, IdeCommonImg::xml(), THISBACK(Xml));
menu.AddMenu(!designer, AK_JSON, IdeCommonImg::json(), THISBACK(Json));
menu.AddMenu(AK_DIRDIFF, DiffImg::DirDiff(), THISBACK(DoDirDiff));
}
menu.Separator();
menu.Add(AK_BROWSETOPICS, IdeImg::help(), THISBACK(ShowTopics));

View file

@ -366,3 +366,40 @@ void Ide::SyncSvnDir(const String& working)
{
SyncSvnDirs(Vector<String>() << working);
}
void Ide::DoDirDiff()
{
Index<String> dir;
Vector<String> d = GetUppDirs();
for(int i = 0; i < d.GetCount(); i++)
dir.FindAdd(d[i]);
FindFile ff(ConfigFile("*.bm"));
while(ff) {
VectorMap<String, String> var;
LoadVarFile(ff.GetPath(), var);
Vector<String> p = Split(var.Get("UPP", String()), ';');
for(int i = 0; i < p.GetCount(); i++)
dir.FindAdd(p[i]);
ff.Next();
}
String n = GetFileFolder(editfile);
if(n.GetCount())
dir.FindAdd(n);
SortIndex(dir);
static DirDiffDlg dlg;
for(int i = 0; i < dir.GetCount(); i++) {
dlg.Dir1AddList(dir[i]);
dlg.Dir2AddList(dir[i]);
}
if(d.GetCount())
dlg.Dir1(d[0]);
if(!dlg.IsOpen()) {
dlg.SetFont(veditorfont);
dlg.Maximize();
dlg.OpenMain();
}
else
dlg.SetFocus();
}