Kaydet (Commit) 3ebfc5b9 authored tarafından Miklos Vajna's avatar Miklos Vajna

svx lok: add LOK_CALLBACK_GRAPHIC_VIEW_SELECTION

So a view can be aware where the graphic selections of other views are.

Change-Id: I0cc420cfe4bf3824fbfa1a58da889cac5e9a7b60
Reviewed-on: https://gerrit.libreoffice.org/26863Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.co.uk>
Tested-by: 's avatarJenkins <ci@libreoffice.org>
üst a2c09913
......@@ -446,6 +446,7 @@ CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, Li
m_states.emplace(LOK_CALLBACK_TEXT_SELECTION_END, "NIL");
m_states.emplace(LOK_CALLBACK_TEXT_SELECTION, "NIL");
m_states.emplace(LOK_CALLBACK_GRAPHIC_SELECTION, "NIL");
m_states.emplace(LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "NIL");
m_states.emplace(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, "NIL");
m_states.emplace(LOK_CALLBACK_INVALIDATE_VIEW_CURSOR , "NIL");
m_states.emplace(LOK_CALLBACK_STATE_CHANGED, "NIL");
......@@ -552,6 +553,7 @@ void CallbackFlushHandler::queue(const int type, const char* data)
case LOK_CALLBACK_TEXT_SELECTION_END:
case LOK_CALLBACK_TEXT_SELECTION:
case LOK_CALLBACK_GRAPHIC_SELECTION:
case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
case LOK_CALLBACK_MOUSE_POINTER:
case LOK_CALLBACK_CELL_CURSOR:
case LOK_CALLBACK_CELL_VIEW_CURSOR:
......
......@@ -358,6 +358,22 @@ typedef enum
*/
LOK_CALLBACK_CELL_VIEW_CURSOR,
/**
* The size and/or the position of a graphic selection in one of the other
* views has changed.
*
* The payload format:
*
* {
* "viewId": "..."
* "selection": "..."
* }
*
* - viewId is a value returned earlier by lok::Document::createView()
* - selection uses the format of LOK_CALLBACK_INVALIDATE_TILES.
*/
LOK_CALLBACK_GRAPHIC_VIEW_SELECTION,
}
LibreOfficeKitCallbackType;
......
......@@ -101,9 +101,12 @@ struct LOKDocViewPrivateImpl
/// Position and size of the selection end.
GdkRectangle m_aTextSelectionEnd;
GdkRectangle m_aGraphicSelection;
/// Position and size of the graphic view selections. The current view can only
/// see them, can't modify them. Key is the view id.
std::map<int, GdkRectangle> m_aGraphicViewSelections;
GdkRectangle m_aCellCursor;
/// Position and size of the cell view cursors. The current view can only
//see / them, can't modify them. Key is the view id.
/// see them, can't modify them. Key is the view id.
std::map<int, GdkRectangle> m_aCellViewCursors;
gboolean m_bInDragGraphicSelection;
......@@ -323,6 +326,8 @@ callbackTypeToString (int nType)
return "LOK_CALLBACK_CURSOR_VISIBLE";
case LOK_CALLBACK_GRAPHIC_SELECTION:
return "LOK_CALLBACK_GRAPHIC_SELECTION";
case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
return "LOK_CALLBACK_GRAPHIC_VIEW_SELECTION";
case LOK_CALLBACK_CELL_CURSOR:
return "LOK_CALLBACK_CELL_CURSOR";
case LOK_CALLBACK_HYPERLINK_CLICKED:
......@@ -1108,6 +1113,25 @@ callback (gpointer pData)
gtk_widget_queue_draw(GTK_WIDGET(pDocView));
}
break;
case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
{
std::stringstream aStream(pCallback->m_aPayload);
boost::property_tree::ptree aTree;
boost::property_tree::read_json(aStream, aTree);
int nViewId = aTree.get<int>("viewId");
const std::string& rRectangle = aTree.get<std::string>("selection");
if (rRectangle != "EMPTY")
priv->m_aGraphicViewSelections[nViewId] = payloadToRectangle(pDocView, rRectangle.c_str());
else
{
auto it = priv->m_aGraphicViewSelections.find(nViewId);
if (it != priv->m_aGraphicViewSelections.end())
priv->m_aGraphicViewSelections.erase(it);
}
gtk_widget_queue_draw(GTK_WIDGET(pDocView));
break;
}
break;
case LOK_CALLBACK_CELL_CURSOR:
{
if (pCallback->m_aPayload != "EMPTY")
......@@ -1271,7 +1295,8 @@ renderHandle(LOKDocView* pDocView,
static void
renderGraphicHandle(LOKDocView* pDocView,
cairo_t* pCairo,
const GdkRectangle& rSelection)
const GdkRectangle& rSelection,
const GdkRGBA& rColor)
{
LOKDocViewPrivate& priv = getPrivate(pDocView);
int nHandleWidth = 9, nHandleHeight = 9;
......@@ -1325,7 +1350,7 @@ renderGraphicHandle(LOKDocView* pDocView,
priv->m_aGraphicHandleRects[i].width = nHandleWidth;
priv->m_aGraphicHandleRects[i].height = nHandleHeight;
cairo_set_source_rgb(pCairo, 0, 0, 0);
cairo_set_source_rgb(pCairo, rColor.red, rColor.green, rColor.blue);
cairo_rectangle(pCairo, x, y, nHandleWidth, nHandleHeight);
cairo_fill(pCairo);
}
......@@ -1586,7 +1611,17 @@ renderOverlay(LOKDocView* pDocView, cairo_t* pCairo)
}
if (!isEmptyRectangle(priv->m_aGraphicSelection))
renderGraphicHandle(pDocView, pCairo, priv->m_aGraphicSelection);
{
GdkRGBA aBlack{0, 0, 0, 0};
renderGraphicHandle(pDocView, pCairo, priv->m_aGraphicSelection, aBlack);
}
// Graphic selections of other views.
for (std::pair<const int, GdkRectangle>& rPair : priv->m_aGraphicViewSelections)
{
const GdkRGBA& rDark = getDarkColor(rPair.first);
renderGraphicHandle(pDocView, pCairo, rPair.second, rDark);
}
// Draw the cell cursor.
if (!isEmptyRectangle(priv->m_aCellCursor))
......
......@@ -12,6 +12,7 @@
#include <test/xmltesttools.hxx>
#include <boost/property_tree/json_parser.hpp>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <sfx2/lokhelper.hxx>
#include <com/sun/star/frame/Desktop.hpp>
#include <comphelper/dispatchcommand.hxx>
#include <comphelper/processfactory.hxx>
......@@ -62,6 +63,7 @@ public:
void testPartHash();
void testResizeTable();
void testResizeTableColumn();
void testViewCursors();
CPPUNIT_TEST_SUITE(SdTiledRenderingTest);
CPPUNIT_TEST(testRegisterCallback);
......@@ -81,6 +83,7 @@ public:
CPPUNIT_TEST(testPartHash);
CPPUNIT_TEST(testResizeTable);
CPPUNIT_TEST(testResizeTableColumn);
CPPUNIT_TEST(testViewCursors);
CPPUNIT_TEST_SUITE_END();
private:
......@@ -806,6 +809,71 @@ void SdTiledRenderingTest::testResizeTableColumn()
comphelper::LibreOfficeKit::setActive(false);
}
class ViewCallback
{
public:
bool m_bGraphicSelectionInvalidated;
bool m_bGraphicViewSelectionInvalidated;
ViewCallback()
: m_bGraphicSelectionInvalidated(false),
m_bGraphicViewSelectionInvalidated(false)
{
}
static void callback(int nType, const char* pPayload, void* pData)
{
static_cast<ViewCallback*>(pData)->callbackImpl(nType, pPayload);
}
void callbackImpl(int nType, const char* /*pPayload*/)
{
switch (nType)
{
case LOK_CALLBACK_GRAPHIC_SELECTION:
{
m_bGraphicSelectionInvalidated = true;
}
break;
case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
{
m_bGraphicViewSelectionInvalidated = true;
}
break;
}
}
};
void SdTiledRenderingTest::testViewCursors()
{
comphelper::LibreOfficeKit::setActive();
// Create two views.
SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
ViewCallback aView1;
SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1);
SfxLokHelper::createView();
ViewCallback aView2;
SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView2);
// Select the shape in the second view.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pActualPage = pViewShell->GetActualPage();
SdrObject* pObject = pActualPage->GetObj(0);
SdrView* pView = pViewShell->GetView();
pView->MarkObj(pObject, pView->GetSdrPageView());
Scheduler::ProcessEventsToIdle();
// First view notices that there was a selection change in the other view.
CPPUNIT_ASSERT(aView1.m_bGraphicViewSelectionInvalidated);
// Second view notices that there was a selection change in its own view.
CPPUNIT_ASSERT(aView2.m_bGraphicSelectionInvalidated);
mxComponent->dispose();
mxComponent.clear();
comphelper::LibreOfficeKit::setActive(false);
}
CPPUNIT_TEST_SUITE_REGISTRATION(SdTiledRenderingTest);
CPPUNIT_PLUGIN_IMPLEMENT();
......
......@@ -1473,9 +1473,11 @@ void SfxViewShell::libreOfficeKitViewCallback(int nType, const char* pPayload) c
switch (nType)
{
case LOK_CALLBACK_TEXT_SELECTION:
case LOK_CALLBACK_TEXT_VIEW_SELECTION:
case LOK_CALLBACK_TEXT_SELECTION_START:
case LOK_CALLBACK_TEXT_SELECTION_END:
case LOK_CALLBACK_GRAPHIC_SELECTION:
case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
return;
}
}
......
......@@ -53,6 +53,7 @@
#include <editeng/editdata.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <comphelper/lok.hxx>
#include <sfx2/lokhelper.hxx>
#include <sfx2/viewsh.hxx>
using namespace com::sun::star;
......@@ -705,7 +706,10 @@ void SdrMarkView::SetMarkHandles()
{
// Suppress handles -> empty graphic selection.
if(SfxViewShell* pViewShell = SfxViewShell::Current())
{
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_GRAPHIC_SELECTION, "EMPTY");
SfxLokHelper::notifyOtherViews(pViewShell, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY");
}
}
return;
}
......@@ -726,7 +730,10 @@ void SdrMarkView::SetMarkHandles()
{
// The table shape has selected cells, which provide text selection already -> no graphic selection.
if(SfxViewShell* pViewShell = SfxViewShell::Current())
{
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_GRAPHIC_SELECTION, "EMPTY");
SfxLokHelper::notifyOtherViews(pViewShell, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY");
}
return;
}
}
......@@ -759,7 +766,10 @@ void SdrMarkView::SetMarkHandles()
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, "");
}
if(SfxViewShell* pViewShell = SfxViewShell::Current())
{
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_GRAPHIC_SELECTION, sSelection.getStr());
SfxLokHelper::notifyOtherViews(pViewShell, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", sSelection);
}
}
if (bFrmHdl)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment