Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  DropTarget.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
#include <com/sun/star/datatransfer/XTransferable.hpp>
#include <com/sun/star/datatransfer/dnd/DropTargetDragEnterEvent.hpp>
#include <cppuhelper/interfacecontainer.hxx>
#include "clipboard.hxx"
#include "DropTarget.hxx"
#include "DragActionConversion.hxx"
#include "DragSource.hxx"
#include <rtl/ustring.h>
#include <osx/salframe.h>
#include <osx/salframeview.h>
#include <cppuhelper/supportsservice.hxx>

using namespace cppu;
using namespace osl;
using namespace com::sun::star::datatransfer;
using namespace com::sun::star::datatransfer::dnd;
using namespace com::sun::star::datatransfer::dnd::DNDConstants;
using namespace com::sun::star::datatransfer::clipboard;
using namespace com::sun::star::lang;
using namespace com::sun::star::uno;
using namespace com::sun::star;
using namespace comphelper;

static OUString dropTarget_getImplementationName()
{
    return "com.sun.star.comp.datatransfer.dnd.OleDropTarget_V1";
}

static Sequence<OUString> dropTarget_getSupportedServiceNames()
{
    return { OUString("com.sun.star.datatransfer.dnd.OleDropTarget") };
}

namespace /* private */
{
    // Cocoa's coordinate system has its origin lower-left, VCL's
    // coordinate system upper-left hence we need to transform
    // coordinates

    void CocoaToVCL(NSPoint& rPoint, const NSRect& bounds)
    {
        rPoint.y = bounds.size.height - rPoint.y;
    }
}

@implementation DropTargetHelper

-(DropTargetHelper*)initWithDropTarget:(DropTarget*)pdt
{
    self = [super init];

    if (self)
    {
        mDropTarget = pdt;
    }

    return self;
}

-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
    return mDropTarget->draggingEntered(sender);
}

-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
{
    return mDropTarget->draggingUpdated(sender);
}

-(void)draggingExited:(id <NSDraggingInfo>)sender
{
    mDropTarget->draggingExited(sender);
}

-(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
{
    (void) sender;
    return DropTarget::prepareForDragOperation();
}

-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
    (void) sender;
    return mDropTarget->performDragOperation();
}

-(void)concludeDragOperation:(id <NSDraggingInfo>)sender
{
    mDropTarget->concludeDragOperation(sender);
}

@end

DropTarget::DropTarget() :
    WeakComponentImplHelper<XInitialization, XDropTarget, XDropTargetDragContext, XDropTargetDropContext, XServiceInfo>(m_aMutex),
    mView(nil),
    mpFrame(nullptr),
    mDropTargetHelper(nil),
    mbActive(false),
    mDragSourceSupportedActions(DNDConstants::ACTION_NONE),
    mSelectedDropAction(DNDConstants::ACTION_NONE),
    mDefaultActions(DNDConstants::ACTION_COPY_OR_MOVE | DNDConstants::ACTION_LINK | DNDConstants::ACTION_DEFAULT)
{
    mDataFlavorMapper = std::make_shared<DataFlavorMapper>();
}

DropTarget::~DropTarget()
{
    if( AquaSalFrame::isAlive( mpFrame ) )
        [static_cast<id <DraggingDestinationHandler>>(mView) unregisterDraggingDestinationHandler:mDropTargetHelper];
    [mDropTargetHelper release];
}

sal_Int8 DropTarget::determineDropAction(sal_Int8 dropActions, id sender) const
{
    sal_Int8 dropAct = dropActions;
    bool srcAndDestEqual = false;

    if ([sender draggingSource] != nil)
    {
        // Internal DnD
        NSView* destView = [[sender draggingDestinationWindow] contentView];
        srcAndDestEqual = (DragSource::g_DragSourceView == destView);
    }

    // If ACTION_DEFAULT is set this means NSDragOperationGeneric
    // has been set and we map this to ACTION_MOVE or ACTION_COPY
    // depending on whether or not source and dest are equal,
    // this hopefully satisfies all parties
    if( (dropActions == DNDConstants::ACTION_DEFAULT)
        || ((dropActions == mDragSourceSupportedActions)
        && !(~mDragSourceSupportedActions & DNDConstants::ACTION_COPY_OR_MOVE ) ) )
    {
        dropAct = srcAndDestEqual ? DNDConstants::ACTION_MOVE :
        DNDConstants::ACTION_COPY;
    }
     // if more than one drop actions have been specified
     // set ACTION_DEFAULT in order to let the drop target
     // decide which one to use
    else if (dropActions != DNDConstants::ACTION_NONE &&
            dropActions != DNDConstants::ACTION_MOVE &&
            dropActions != DNDConstants::ACTION_COPY &&
            dropActions != DNDConstants::ACTION_LINK)
    {
        if (srcAndDestEqual)
        {
            dropAct = dropActions;
        }
        else // source and destination are different
        {
            if (dropActions & DNDConstants::ACTION_COPY)
                dropAct = DNDConstants::ACTION_COPY;
            else if (dropActions & DNDConstants::ACTION_MOVE)
                dropAct = DNDConstants::ACTION_MOVE;
            else if (dropActions & DNDConstants::ACTION_LINK)
                dropAct = DNDConstants::ACTION_LINK;
        }

        dropAct |= DNDConstants::ACTION_DEFAULT;
    }

    return dropAct;
}

NSDragOperation DropTarget::draggingEntered(id sender)
{
    // Initially when DnD will be started no modifier key can be pressed yet
    // thus we are getting all actions that the drag source supports, we save
    // this value because later the system masks the drag source actions if
    // a modifier key will be pressed
    mDragSourceSupportedActions = SystemToOfficeDragActions([sender draggingSourceOperationMask]);

    // Only if the drop target is really interested in the drag actions
    // supported by the source
    if (mDragSourceSupportedActions & mDefaultActions)
    {
        sal_Int8 currentAction = determineDropAction(mDragSourceSupportedActions, sender);

        NSRect bounds = [mView bounds];
        NSPoint mouseLoc = [NSEvent mouseLocation];

        id wnd = [mView window];
        NSPoint dragLocation = [mView convertPoint:[wnd convertRectFromScreen:NSMakeRect(mouseLoc.x, mouseLoc.y, 1, 1)].origin fromView:nil];

        CocoaToVCL(dragLocation, bounds);

        sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x);
        sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y);

        NSPasteboard* dragPboard = [sender draggingPasteboard];
        mXCurrentDragClipboard = new AquaClipboard(dragPboard, false);

        uno::Reference<XTransferable> xTransferable = DragSource::g_XTransferable.is() ?
                                                      DragSource::g_XTransferable : mXCurrentDragClipboard->getContents();

        DropTargetDragEnterEvent dtdee(getXWeak(),
                                        0,
                                        this,
                                        currentAction,
                                        posX,
                                        posY,
                                        mDragSourceSupportedActions,
                                        xTransferable->getTransferDataFlavors());

        fire_dragEnter(dtdee);
    }

    return OfficeToSystemDragActions(mSelectedDropAction);
}

NSDragOperation DropTarget::draggingUpdated(id sender)
{
    sal_Int8 currentDragSourceActions =
    SystemToOfficeDragActions([sender draggingSourceOperationMask]);
    NSDragOperation dragOp = NSDragOperationNone;

    if (currentDragSourceActions & mDefaultActions)
    {
        sal_Int8 currentAction = determineDropAction(currentDragSourceActions, sender);
        NSRect bounds = [mView bounds];
        NSPoint mouseLoc = [NSEvent mouseLocation];

        id wnd = [mView window];
        NSPoint dragLocation = [mView convertPoint:[wnd convertRectFromScreen:NSMakeRect(mouseLoc.x, mouseLoc.y, 1, 1)].origin fromView:nil];

        CocoaToVCL(dragLocation, bounds);

        sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x);
        sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y);

        DropTargetDragEvent dtde(getXWeak(),
                               0,
                               this,
                               currentAction,
                               posX,
                               posY,
                               mDragSourceSupportedActions);

        fire_dragOver(dtde);

        // drag over callbacks likely have rendered something
        [mView setNeedsDisplay: true];

        dragOp = OfficeToSystemDragActions(mSelectedDropAction);

        //NSLog(@"Drag update: Source actions: %x proposed action %x selected action %x", mDragSourceSupportedActions, currentAction, mSelectedDropAction);
    }

    if (dragOp == NSDragOperationNone)
        [[NSCursor operationNotAllowedCursor] set];
    else if (dragOp == NSDragOperationCopy)
        [[NSCursor dragCopyCursor] set];
    else
        [[NSCursor arrowCursor] set];

    return dragOp;
}

void DropTarget::draggingExited(id /*sender*/)
{
    DropTargetEvent dte(getXWeak(), 0);
    fire_dragExit(dte);
    mDragSourceSupportedActions = DNDConstants::ACTION_NONE;
    mSelectedDropAction = DNDConstants::ACTION_NONE;
    [[NSCursor arrowCursor] set];
}

BOOL DropTarget::prepareForDragOperation()
{
    return true;
}

BOOL DropTarget::performDragOperation()
{
    bool bSuccess = false;

    if (mSelectedDropAction != DNDConstants::ACTION_NONE)
    {
        uno::Reference<XTransferable> xTransferable = DragSource::g_XTransferable;

        if (!DragSource::g_XTransferable.is())
        {
            xTransferable = mXCurrentDragClipboard->getContents();
        }

        NSRect bounds = [mView bounds];
        NSPoint mouseLoc = [NSEvent mouseLocation];

        id wnd = [mView window];
        NSPoint dragLocation = [mView convertPoint:[wnd convertRectFromScreen:NSMakeRect(mouseLoc.x, mouseLoc.y, 1, 1)].origin fromView:nil];

        CocoaToVCL(dragLocation, bounds);

        sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x);
        sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y);

        DropTargetDropEvent dtde(getXWeak(),
                               0,
                               this,
                               mSelectedDropAction,
                               posX,
                               posY,
                               mDragSourceSupportedActions,
                               xTransferable);

        fire_drop(dtde);

        bSuccess = true;
    }

    return bSuccess;
}

void DropTarget::concludeDragOperation(id /*sender*/)
{
    mDragSourceSupportedActions = DNDConstants::ACTION_NONE;
    mSelectedDropAction = DNDConstants::ACTION_NONE;
    mXCurrentDragClipboard.clear();
    [[NSCursor arrowCursor] set];
}

// called from WeakComponentImplHelperX::dispose
// WeakComponentImplHelper calls disposing before it destroys
// itself.
void SAL_CALL DropTarget::disposing()
{
}

void SAL_CALL DropTarget::initialize(const Sequence< Any >& aArguments)
{
    if (aArguments.getLength() < 2)
    {
        throw RuntimeException("DropTarget::initialize: Cannot install window event handler",
                               getXWeak());
    }

    Any pNSView = aArguments[0];
    sal_uInt64 tmp = 0;
    pNSView >>= tmp;
    mView = reinterpret_cast<id>(tmp);
    mpFrame = [static_cast<SalFrameView*>(mView) getSalFrame];

    mDropTargetHelper = [[DropTargetHelper alloc] initWithDropTarget: this];

    [static_cast<id <DraggingDestinationHandler>>(mView) registerDraggingDestinationHandler:mDropTargetHelper];
    [mView registerForDraggedTypes: DataFlavorMapper::getAllSupportedPboardTypes()];

    id wnd = [mView window];
    NSWindow* parentWnd = [wnd parentWindow];
    unsigned int topWndStyle = (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable);
    unsigned int wndStyles = [wnd styleMask] & topWndStyle;

    if (parentWnd == nil && (wndStyles == topWndStyle))
    {
        [wnd registerDraggingDestinationHandler:mDropTargetHelper];
SAL_WNODEPRECATED_DECLARATIONS_PUSH
            // "'NSFilenamesPboardType' is deprecated: first deprecated in macOS 10.14 - Create
            // multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead"
        [wnd registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
SAL_WNODEPRECATED_DECLARATIONS_POP
    }
}

void SAL_CALL DropTarget::addDropTargetListener(const uno::Reference<XDropTargetListener>& dtl)
{
    rBHelper.addListener(cppu::UnoType<decltype(dtl)>::get(), dtl);
}

void SAL_CALL DropTarget::removeDropTargetListener(const uno::Reference<XDropTargetListener>& dtl)
{
    rBHelper.removeListener(cppu::UnoType<decltype(dtl)>::get(), dtl);
}

sal_Bool SAL_CALL DropTarget::isActive(  )
{
    return mbActive;
}

void SAL_CALL DropTarget::setActive(sal_Bool active)
{
    mbActive = active;
}

sal_Int8 SAL_CALL DropTarget::getDefaultActions()
{
    return mDefaultActions;
}

void SAL_CALL DropTarget::setDefaultActions(sal_Int8 actions)
{
    OSL_ENSURE( actions < 8, "No valid default actions");
    mDefaultActions= actions;
}

void SAL_CALL DropTarget::acceptDrag(sal_Int8 dragOperation)
{
    mSelectedDropAction = dragOperation;
}

void SAL_CALL DropTarget::rejectDrag()
{
    mSelectedDropAction = DNDConstants::ACTION_NONE;
}

void SAL_CALL DropTarget::acceptDrop(sal_Int8 dropOperation)
{
    mSelectedDropAction = dropOperation;
}

void SAL_CALL DropTarget::rejectDrop()
{
    mSelectedDropAction = DNDConstants::ACTION_NONE;
}

void SAL_CALL DropTarget::dropComplete(sal_Bool success)
{
    // Reset the internal transferable used as shortcut in case this is
    // an internal D&D operation
    DragSource::g_XTransferable.clear();
    DragSource::g_DropSuccessSet = true;
    DragSource::g_DropSuccess = success;
}

void DropTarget::fire_drop( const DropTargetDropEvent& dte)
{
    OInterfaceContainerHelper* pContainer= rBHelper.getContainer( cppu::UnoType<XDropTargetListener>::get());
    if( pContainer)
    {
        OInterfaceIteratorHelper iter( *pContainer);
        while( iter.hasMoreElements())
        {
            uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));

            try { listener->drop( dte); }
            catch(RuntimeException&) {}
        }
    }
}

void DropTarget::fire_dragEnter(const DropTargetDragEnterEvent& e)
{
    OInterfaceContainerHelper* pContainer= rBHelper.getContainer( cppu::UnoType<XDropTargetListener>::get());
    if( pContainer)
    {
        OInterfaceIteratorHelper iter( *pContainer);
        while( iter.hasMoreElements())
        {
            uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));

            try { listener->dragEnter( e); }
            catch (RuntimeException&) {}
        }
    }
}

void DropTarget::fire_dragExit(const DropTargetEvent& dte)
{
    OInterfaceContainerHelper* pContainer= rBHelper.getContainer( cppu::UnoType<XDropTargetListener>::get());

    if( pContainer)
    {
        OInterfaceIteratorHelper iter( *pContainer);
        while( iter.hasMoreElements())
        {
            uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));

            try { listener->dragExit( dte); }
            catch (RuntimeException&) {}
        }
    }
}

void DropTarget::fire_dragOver(const DropTargetDragEvent& dtde)
{
    OInterfaceContainerHelper* pContainer= rBHelper.getContainer( cppu::UnoType<XDropTargetListener>::get());
    if( pContainer)
    {
        OInterfaceIteratorHelper iter( *pContainer );
        while( iter.hasMoreElements())
        {
            uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));

            try { listener->dragOver( dtde); }
            catch (RuntimeException&) {}
        }
    }
}

void DropTarget::fire_dropActionChanged(const DropTargetDragEvent& dtde)
{
    OInterfaceContainerHelper* pContainer= rBHelper.getContainer( cppu::UnoType<XDropTargetListener>::get());
    if( pContainer)
    {
        OInterfaceIteratorHelper iter( *pContainer);
        while( iter.hasMoreElements())
        {
            uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));

            try { listener->dropActionChanged( dtde); }
            catch (RuntimeException&) {}
        }
    }
}

OUString SAL_CALL DropTarget::getImplementationName()
{
    return dropTarget_getImplementationName();
}

sal_Bool SAL_CALL DropTarget::supportsService( const OUString& ServiceName )
{
    return cppu::supportsService(this, ServiceName);
}

Sequence< OUString > SAL_CALL DropTarget::getSupportedServiceNames(  )
{
    return dropTarget_getSupportedServiceNames();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=95 H=93 G=93

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge