* Reindent & style fix.

* Added copy-to-clipboard.
* Added picture and bitmap clipboard formats.
Now you can just paste into either a text or graphics app. Even Gobe uses the text in word processor and bitmap in picture editor :)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23855 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
François Revol
2008-02-03 21:37:23 +00:00
parent 967d72041f
commit bb00cd45ed
3 changed files with 187 additions and 113 deletions
+182 -111
View File
@@ -16,10 +16,13 @@
#include <Application.h> #include <Application.h>
#include <Beep.h> #include <Beep.h>
#include <Bitmap.h>
#include <Clipboard.h>
#include <DataIO.h> #include <DataIO.h>
#include <File.h> #include <File.h>
#include <NodeInfo.h> #include <NodeInfo.h>
#include <Path.h> #include <Path.h>
#include <Picture.h>
#include <String.h> #include <String.h>
@@ -222,128 +225,154 @@ SudokuView::SaveTo(BDataIO &stream, uint32 as)
nodeInfo.SetTo(file); nodeInfo.SetTo(file);
switch (as) { switch (as) {
case kExportAsText: case kExportAsText:
text = "# Written by Sudoku\n\n"; text = "# Written by Sudoku\n\n";
stream.Write(text.String(), text.Length()); stream.Write(text.String(), text.Length());
line = text.LockBuffer(1024); line = text.LockBuffer(1024);
memset(line, 0, 1024); memset(line, 0, 1024);
for (uint32 y = 0; y < fField->Size(); y++) { for (uint32 y = 0; y < fField->Size(); y++) {
for (uint32 x = 0; x < fField->Size(); x++) { for (uint32 x = 0; x < fField->Size(); x++) {
if (x != 0 && x % fBlockSize == 0) if (x != 0 && x % fBlockSize == 0)
line[i++] = ' '; line[i++] = ' ';
_SetText(&line[i++], fField->ValueAt(x, y)); _SetText(&line[i++], fField->ValueAt(x, y));
}
line[i++] = '\n';
} }
line[i++] = '\n'; text.UnlockBuffer();
}
text.UnlockBuffer();
stream.Write(text.String(), text.Length()); stream.Write(text.String(), text.Length());
if (file) if (file)
nodeInfo.SetType("text/plain"); nodeInfo.SetType("text/plain");
return B_OK; return B_OK;
case kExportAsHTML: case kExportAsHTML:
{ {
bool netPositiveFriendly = false; bool netPositiveFriendly = false;
text = "<html>\n<head>\n<!-- Written by Sudoku -->\n" text = "<html>\n<head>\n<!-- Written by Sudoku -->\n"
"<style type=\"text/css\">\n" "<style type=\"text/css\">\n"
/* "table.sudoku { background: #000000; border:0; border-collapse: collapse; cellpadding: 10px; cellspacing: 10px; width: 300px; height: 300px; }\n"
"table.sudoku { background: #000000; border:0; cellpadding: 10px; cellspacing: 1px; width: 300px; height: 300px; }\n" "td.sudoku { background: #ffffff; border-color: black; border-left: none ; border-top: none ; /*border: none;*/ text-align: center; }\n"
"td.sudoku { background: #ffffff; border: 0; text-align: center; }\n" "td.sudoku_initial { }\n"
"td.sudoku_initial { }\n" "td.sudoku_filled { color: blue; }\n"
"td.sudoku_filled { color: blue; }\n" "td.sudoku_empty { }\n"
"td.sudoku_empty { }\n" // border styles: right bottom (none, solid or large)
*/
"table.sudoku { background: #000000; border:0; border-collapse: collapse; cellpadding: 10px; cellspacing: 10px; width: 300px; height: 300px; }\n"
"td.sudoku { background: #ffffff; border-color: black; border-left: none ; border-top: none ; /*border: none;*/ text-align: center; }\n"
"td.sudoku_initial { }\n"
"td.sudoku_filled { color: blue; }\n"
"td.sudoku_empty { }\n"
// border styles: right bottom (none, solid or large)
#define BS_N "none" #define BS_N "none"
#define BS_S "solid 1px black" #define BS_S "solid 1px black"
#define BS_L "solid 3px black" #define BS_L "solid 3px black"
"td.sudoku_nn { border-right: " BS_N "; border-bottom: " BS_N "; }\n" "td.sudoku_nn { border-right: " BS_N "; border-bottom: " BS_N "; }\n"
"td.sudoku_sn { border-right: " BS_S "; border-bottom: " BS_N "; }\n" "td.sudoku_sn { border-right: " BS_S "; border-bottom: " BS_N "; }\n"
"td.sudoku_ns { border-right: " BS_N "; border-bottom: " BS_S "; }\n" "td.sudoku_ns { border-right: " BS_N "; border-bottom: " BS_S "; }\n"
"td.sudoku_ss { border-right: " BS_S "; border-bottom: " BS_S "; }\n" "td.sudoku_ss { border-right: " BS_S "; border-bottom: " BS_S "; }\n"
"td.sudoku_nl { border-right: " BS_N "; border-bottom: " BS_L "; }\n" "td.sudoku_nl { border-right: " BS_N "; border-bottom: " BS_L "; }\n"
"td.sudoku_sl { border-right: " BS_S "; border-bottom: " BS_L "; }\n" "td.sudoku_sl { border-right: " BS_S "; border-bottom: " BS_L "; }\n"
"td.sudoku_ln { border-right: " BS_L "; border-bottom: " BS_N "; }\n" "td.sudoku_ln { border-right: " BS_L "; border-bottom: " BS_N "; }\n"
"td.sudoku_ls { border-right: " BS_L "; border-bottom: " BS_S "; }\n" "td.sudoku_ls { border-right: " BS_L "; border-bottom: " BS_S "; }\n"
"td.sudoku_ll { border-right: " BS_L "; border-bottom: " BS_L "; }\n" "td.sudoku_ll { border-right: " BS_L "; border-bottom: " BS_L "; }\n"
"</style>\n" "</style>\n"
"</head>\n<body>\n\n"; "</head>\n<body>\n\n";
/*if (file)*/ stream.Write(text.String(), text.Length());
stream.Write(text.String(), text.Length());
text = "<table"; text = "<table";
if (netPositiveFriendly) if (netPositiveFriendly)
text << " border=\"1\""; text << " border=\"1\"";
text << " class=\"sudoku\">"; text << " class=\"sudoku\">";
stream.Write(text.String(), text.Length()); stream.Write(text.String(), text.Length());
//XXX: make border larger on %3 text = "";
BString divider;
text = ""; divider << (int)(100.0 / fField->Size()) << "%";
BString divider; for (uint32 y = 0; y < fField->Size(); y++) {
divider << (int)(100.0 / fField->Size()) << "%"; text << "<tr height=\"" << divider << "\">\n";
for (uint32 y = 0; y < fField->Size(); y++) { for (uint32 x = 0; x < fField->Size(); x++) {
text << "<tr height=\"" << divider << "\">\n"; char buff[2];
for (uint32 x = 0; x < fField->Size(); x++) { _SetText(buff, fField->ValueAt(x, y));
char buff[2];
_SetText(buff, fField->ValueAt(x, y)); char border_right = 's';
char border_bottom = 's';
char border_right = 's'; if ((x+1) % fField->BlockSize() == 0)
char border_bottom = 's'; border_right = 'l';
if ((x+1) % fField->BlockSize() == 0) if ((y+1) % fField->BlockSize() == 0)
border_right = 'l'; border_bottom = 'l';
if ((y+1) % fField->BlockSize() == 0) if (x == fField->Size() - 1)
border_bottom = 'l'; border_right = 'n';
if (x == fField->Size() - 1) if (y == fField->Size() - 1)
border_right = 'n'; border_bottom = 'n';
if (y == fField->Size() - 1)
border_bottom = 'n'; if (fField->ValueAt(x, y) == 0) {
text << "<td width=\"" << divider << "\" ";
if (fField->ValueAt(x, y) == 0) { text << "class=\"sudoku sudoku_empty sudoku_" << border_right << border_bottom << "\">\n";
text << "<td width=\"" << divider << "\" "; text << "&nbsp;";
text << "class=\"sudoku sudoku_empty sudoku_" << border_right << border_bottom << "\">\n"; } else if (fField->FlagsAt(x, y) & kInitialValue) {
text << "&nbsp;"; text << "<td width=\"" << divider << "\" ";
} else if (fField->FlagsAt(x, y) & kInitialValue) { text << "class=\"sudoku sudoku_initial sudoku_" << border_right << border_bottom << "\">\n";
text << "<td width=\"" << divider << "\" "; if (netPositiveFriendly)
text << "class=\"sudoku sudoku_initial sudoku_" << border_right << border_bottom << "\">\n"; text << "<font color=\"#000000\">";
if (netPositiveFriendly) text << buff;
text << "<font color=\"#000000\">"; if (netPositiveFriendly)
text << buff; text << "</font>";
if (netPositiveFriendly) } else {
text << "</font>"; text << "<td width=\"" << divider << "\" ";
} else { text << "class=\"sudoku sudoku_filled sudoku_" << border_right << border_bottom << "\">\n";
text << "<td width=\"" << divider << "\" "; if (netPositiveFriendly)
text << "class=\"sudoku sudoku_filled sudoku_" << border_right << border_bottom << "\">\n"; text << "<font color=\"#0000ff\">";
if (netPositiveFriendly) text << buff;
text << "<font color=\"#0000ff\">"; if (netPositiveFriendly)
text << buff; text << "</font>";
if (netPositiveFriendly) }
text << "</font>"; text << "</td>\n";
} }
text << "</td>\n"; text << "</tr>\n";
} }
text << "</tr>\n"; text << "</table>\n\n";
}
text << "</table>\n\n";
stream.Write(text.String(), text.Length()); stream.Write(text.String(), text.Length());
text = "</body></html>\n"; text = "</body></html>\n";
/*if (file)*/ stream.Write(text.String(), text.Length());
stream.Write(text.String(), text.Length()); if (file)
if (file) nodeInfo.SetType("text/html");
nodeInfo.SetType("text/html"); return B_OK;
return B_OK; }
} case kExportAsBitmap:
case kExportAsBitmap: {
case kExportAsPicture: BMallocIO mio;
default: status = SaveTo(mio, kExportAsPicture);
return EINVAL; if (status < B_OK)
return status;
mio.Seek(0LL, SEEK_SET);
BPicture picture;
status = picture.Unflatten(&mio);
if (status < B_OK)
return status;
BBitmap *bitmap = new BBitmap(Bounds(), B_BITMAP_ACCEPTS_VIEWS, B_RGB32);
BView *view = new BView(Bounds(), "bitmap", B_FOLLOW_NONE, B_WILL_DRAW);
bitmap->AddChild(view);
if (bitmap->Lock()) {
view->DrawPicture(&picture);
view->Sync();
view->RemoveSelf();
delete view;
bitmap->Unlock();
}
BMessage msg(B_OK);
status = bitmap->Archive(&msg);
if (status >= B_OK) {
status = msg.Flatten(&stream);
}
delete bitmap;
return status;
}
case kExportAsPicture:
{
BPicture picture;
BeginPicture(&picture);
Draw(Bounds());
if (EndPicture()) {
status = picture.Flatten(&stream);
}
return status;
}
default:
return EINVAL;
} }
return status; return status;
@@ -354,7 +383,49 @@ status_t
SudokuView::CopyToClipboard() SudokuView::CopyToClipboard()
{ {
status_t status = EINVAL; status_t status = EINVAL;
BMessage data; BMessage *clip;
if (be_clipboard->Lock()) {
BMallocIO mio;
be_clipboard->Clear();
clip = be_clipboard->Data();
if (clip) {
// first as bitmap as we need to archive to the message
if (SaveTo(mio, kExportAsBitmap) >= B_OK) {
mio.Seek(0LL, SEEK_SET);
// ShowImage wants this... nasty
clip->Unflatten(&mio);
// ArtPaint uses that
clip->AddData("image/bitmap", B_MESSAGE_TYPE, mio.Buffer(), mio.BufferLength());
// Becasso uses that ?
clip->AddData("image/x-be-bitmap", B_MESSAGE_TYPE, mio.Buffer(), mio.BufferLength());
// Gobe Productive uses that...
// QuickRes as well, with a rect field.
clip->AddData("image/x-vnd.Be-bitmap", B_MESSAGE_TYPE, mio.Buffer(), mio.BufferLength());
}
mio.Seek(0LL, SEEK_SET);
mio.SetSize(0LL);
if (SaveTo(mio, kExportAsHTML) >= B_OK)
clip->AddData("text/html", B_MIME_TYPE, mio.Buffer(), mio.BufferLength());
mio.Seek(0LL, SEEK_SET);
mio.SetSize(0LL);
if (SaveTo(mio, kExportAsText) >= B_OK)
clip->AddData("text/plain", B_MIME_TYPE, mio.Buffer(), mio.BufferLength());
mio.Seek(0LL, SEEK_SET);
mio.SetSize(0LL);
// flattened BPicture, anyone handles that ?
if (SaveTo(mio, kExportAsPicture) >= B_OK) {
clip->AddData("text/x-vnd.Be-picture", B_MIME_TYPE, mio.Buffer(), mio.BufferLength());
}
mio.SetSize(0LL);
be_clipboard->Commit();
}
be_clipboard->Unlock();
}
return status; return status;
} }
+2 -2
View File
@@ -39,8 +39,8 @@ public:
status_t SetTo(const char* data); status_t SetTo(const char* data);
status_t SetTo(SudokuField* field); status_t SetTo(SudokuField* field);
status_t SaveTo(entry_ref& ref, uint32 as=kExportAsText); status_t SaveTo(entry_ref& ref, uint32 as = kExportAsText);
status_t SaveTo(BDataIO &to, uint32 as=kExportAsText); status_t SaveTo(BDataIO &to, uint32 as = kExportAsText);
status_t CopyToClipboard(); status_t CopyToClipboard();
+3
View File
@@ -217,6 +217,9 @@ SudokuWindow::SudokuWindow()
*/ */
menu->AddItem(subMenu); menu->AddItem(subMenu);
menu->AddItem(item = new BMenuItem("Copy",
new BMessage(B_COPY), 'C'));
menu->AddSeparatorItem(); menu->AddSeparatorItem();
menu->AddItem(item = new BMenuItem("About Sudoku" B_UTF8_ELLIPSIS, menu->AddItem(item = new BMenuItem("About Sudoku" B_UTF8_ELLIPSIS,