* Copyright (C) 2000-2005 the VideoLAN team
* $Id$
*
- * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
- * Clément Stenac <zorglub@videolan.org>
+ * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
+ * Clément Stenac <zorglub@videolan.org>
*
* This program is free software; you can redistribute it and/OR MODIFy
* it under the terms of the GNU General Public License as published by
*****************************************************************************/
#include "dialogs/playlist.hpp"
#include "dialogs/iteminfo.hpp"
-#include "interface.hpp" // Needed for D&D - TODO: Split
#include "bitmaps/shuffle.xpm"
#include "bitmaps/repeat.xpm"
#include <wx/dynarray.h>
#include <wx/imaglist.h>
+#include <vlc_meta.h>
+#include "charset.h"
+
#define HELP_SHUFFLE N_( "Shuffle" )
#define HELP_LOOP N_( "Repeat All" )
#define HELP_REPEAT N_( "Repeat One" )
static int ItemChanged( vlc_object_t *, const char *,
vlc_value_t, vlc_value_t, void * );
static int ItemAppended( vlc_object_t *p_this, const char *psz_variable,
- vlc_value_t oval, vlc_value_t nval, void *param );
+ vlc_value_t oval, vlc_value_t nval, void *param );
static int ItemDeleted( vlc_object_t *p_this, const char *psz_variable,
- vlc_value_t oval, vlc_value_t nval, void *param );
+ vlc_value_t oval, vlc_value_t nval, void *param );
/*****************************************************************************
* Event Table.
PopupSort_Event,
PopupDel_Event,
PopupInfo_Event,
+ PopupAddNode_Event,
SearchText_Event,
Search_Event,
EVT_MENU( PopupSort_Event, Playlist::OnPopupSort)
EVT_MENU( PopupDel_Event, Playlist::OnPopupDel)
EVT_MENU( PopupInfo_Event, Playlist::OnPopupInfo)
+ EVT_MENU( PopupAddNode_Event, Playlist::OnPopupAddNode)
/* Tree control events */
EVT_TREE_ITEM_ACTIVATED( TreeCtrl_Event, Playlist::OnActivateItem )
EVT_TREE_KEY_DOWN( -1, Playlist::OnKeyDown )
+ EVT_TREE_BEGIN_DRAG( TreeCtrl_Event, Playlist::OnDragItemBegin )
+ EVT_TREE_END_DRAG( TreeCtrl_Event, Playlist::OnDragItemEnd )
EVT_CONTEXT_MENU( Playlist::OnPopup )
protected:
int i_id;
friend class Playlist;
+friend class PlaylistFileDropTarget;
};
/*****************************************************************************
node_popup->Append( PopupSort_Event, wxU(_("Sort this branch")) );
node_popup->Append( PopupDel_Event, wxU(_("Delete")) );
node_popup->Append( PopupInfo_Event, wxU(_("Info")) );
+ node_popup->Append( PopupAddNode_Event, wxU(_("Add node")) );
item_popup = new wxMenu;
item_popup->Append( PopupPlay_Event, wxU(_("Play")) );
#if wxUSE_DRAG_AND_DROP
/* Associate drop targets with the playlist */
- SetDropTarget( new DragAndDrop( p_intf, VLC_TRUE ) );
+ SetDropTarget( new PlaylistFileDropTarget( this ) );
+ menubar->SetDropTarget( new PlaylistFileDropTarget( this ) );
+ toolbar->SetDropTarget( new PlaylistFileDropTarget( this ) );
#endif
i_saved_id = -1;
wxString msg;
wxString duration = wxU( "" );
char *psz_author = vlc_input_item_GetInfo( &p_item->input,
- _("Meta-information"),
- _("Artist"));
+ _(VLC_META_INFO_CAT), _(VLC_META_ARTIST) );
if( !psz_author )
{
UnlockPlaylist( p_intf->p_sys, p_playlist );
else
{
msg = wxString(wxU( psz_author )) + wxT(" - ") +
- wxString(wxU(p_item->input.psz_name)) + duration;
+ wxString(wxU(p_item->input.psz_name)) + duration;
}
free( psz_author );
treectrl->SetItemText( item , msg );
msg_Warn( p_intf, "not implemented" );
}
+void Playlist::OnDragItemBegin( wxTreeEvent& event )
+{
+ event.Allow();
+ draged_tree_item = event.GetItem();
+}
+
+void Playlist::OnDragItemEnd( wxTreeEvent& event )
+{
+ wxTreeItemId dest_tree_item = event.GetItem();
+
+ if( !dest_tree_item.IsOk() ) return;
+
+ /* check that we're not trying to move a node into one of it's children */
+ wxTreeItemId parent = dest_tree_item;
+ while( parent != treectrl->GetRootItem() )
+ {
+ if( draged_tree_item == parent ) return;
+ parent = treectrl->GetItemParent( parent );
+ }
+
+ LockPlaylist( p_intf->p_sys, p_playlist );
+
+ PlaylistItem *p_wxdrageditem =
+ (PlaylistItem *)treectrl->GetItemData( draged_tree_item );
+ PlaylistItem *p_wxdestitem =
+ (PlaylistItem *)treectrl->GetItemData( dest_tree_item );
+ if( !p_wxdrageditem || !p_wxdestitem )
+ {
+ UnlockPlaylist( p_intf->p_sys, p_playlist );
+ return;
+ }
+
+ playlist_item_t *p_drageditem =
+ playlist_ItemGetById(p_playlist, p_wxdrageditem->i_id );
+ playlist_item_t *p_destitem =
+ playlist_ItemGetById(p_playlist, p_wxdestitem->i_id );
+ if( !p_drageditem || !p_destitem )
+ {
+ UnlockPlaylist( p_intf->p_sys, p_playlist );
+ return;
+ }
+
+ if( p_destitem->i_children == -1 )
+ /* this is a leaf */
+ {
+ parent = treectrl->GetItemParent( dest_tree_item );
+ PlaylistItem *p_parent =
+ (PlaylistItem *)treectrl->GetItemData( parent );
+ if( !p_parent )
+ {
+ UnlockPlaylist( p_intf->p_sys, p_playlist );
+ return;
+ }
+ playlist_item_t *p_destitem2 =
+ playlist_ItemGetById( p_playlist, p_parent->i_id );
+ if( !p_destitem2 )
+ {
+ UnlockPlaylist( p_intf->p_sys, p_playlist );
+ return;
+ }
+ int i;
+ for( i = 0; i < p_destitem2->i_children; i++ )
+ {
+ if( p_destitem2->pp_children[i] == p_destitem ) break;
+ }
+ playlist_TreeMove( p_playlist, p_drageditem, p_destitem2,
+ i, i_current_view );
+ }
+ else
+ /* this is a node */
+ {
+ playlist_TreeMove( p_playlist, p_drageditem, p_destitem,
+ 0, i_current_view );
+ }
+
+ UnlockPlaylist( p_intf->p_sys, p_playlist );
+
+ /* FIXME: having this Rebuild() is dirty */
+ Rebuild( VLC_TRUE );
+}
+
+#if wxUSE_DRAG_AND_DROP
+PlaylistFileDropTarget::PlaylistFileDropTarget( Playlist *p ):p( p ){}
+
+/********************************************************************
+ * File Drag And Drop handling
+ ********************************************************************/
+bool PlaylistFileDropTarget::OnDropFiles( wxCoord x, wxCoord y,
+ const wxArrayString& filenames )
+{
+ int i_pos = 0;
+ playlist_item_t *p_dest;
+
+ LockPlaylist( p->p_intf->p_sys, p->p_playlist );
+
+ /* find the destination node and position in that node */
+ const wxPoint pt( x, y );
+ wxTreeItemId item = p->treectrl->HitTest( pt );
+
+ if( !item.IsOk() )
+ {
+ /* We were droped below the last item so we append to the
+ * general node */
+ p_dest = p->p_playlist->p_general;
+ i_pos = PLAYLIST_END;
+ }
+ else
+ {
+ PlaylistItem *p_plitem =
+ (PlaylistItem *)p->treectrl->GetItemData( item );
+ p_dest = playlist_ItemGetById( p->p_playlist, p_plitem->i_id );
+
+ if( p_dest->i_children == -1 )
+ {
+ /* This is a leaf. Append right after it
+ * We thus need to find the parrent node and the position of the
+ * leaf in it's children list */
+ wxTreeItemId parent = p->treectrl->GetItemParent( item );
+ PlaylistItem *p_parent =
+ (PlaylistItem *)p->treectrl->GetItemData( parent );
+ if( !p_parent )
+ {
+ UnlockPlaylist( p->p_intf->p_sys, p->p_playlist );
+ return FALSE;
+ }
+ playlist_item_t *p_node =
+ playlist_ItemGetById( p->p_playlist, p_parent->i_id );
+ if( !p_node )
+ {
+ UnlockPlaylist( p->p_intf->p_sys, p->p_playlist );
+ return FALSE;
+ }
+ for( i_pos = 0; i_pos < p_node->i_children; i_pos++ )
+ {
+ if( p_node->pp_children[i_pos] == p_dest ) break;
+ }
+ p_dest = p_node;
+ }
+ }
+
+ UnlockPlaylist( p->p_intf->p_sys, p->p_playlist );
+
+ /* Put the items in the playlist node */
+ for( size_t i = 0; i < filenames.GetCount(); i++ )
+ {
+ const char *psz_utf8 = wxDnDFromLocale( filenames[i] );
+ playlist_item_t *p_item =
+ playlist_ItemNew( p->p_playlist, psz_utf8, psz_utf8 );
+ playlist_NodeAddItem( p->p_playlist, p_item, p->i_current_view,
+ p_dest, PLAYLIST_PREPARSE, i_pos );
+ wxDnDLocaleFree( psz_utf8 );
+ }
+
+ /* FIXME: having this Rebuild() is dirty */
+ p->Rebuild( VLC_TRUE );
+
+ return TRUE;
+}
+#endif
+
/**********************************************************************
* Menu
**********************************************************************/
UnlockPlaylist( p_intf->p_sys, p_playlist );
}
+void Playlist::OnPopupAddNode( wxCommandEvent& event )
+{
+ wxTextEntryDialog text( NULL, wxU(_( "Please enter node name" )),
+ wxU(_( "Add node" )), wxU(_( "New node" )) );
+ if( text.ShowModal() != wxID_OK ) return;
+
+ char *psz_name = wxFromLocale( text.GetValue() );
+
+ LockPlaylist( p_intf->p_sys, p_playlist );
+
+ PlaylistItem *p_wxitem;
+ playlist_item_t *p_item;
+
+ p_wxitem = (PlaylistItem *)treectrl->GetItemData( i_wx_popup_item );
+
+ p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
+
+ playlist_NodeCreate( p_playlist, i_current_view, psz_name, p_item );
+
+ UnlockPlaylist( p_intf->p_sys, p_playlist );
+ Rebuild( VLC_TRUE );
+
+ wxLocaleFree( psz_name );
+}
+
/*****************************************************************************
* Custom events management
playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t));
memcpy( p_add, nval.p_address, sizeof( playlist_add_t ) );
- if( p_playlist_dialog->i_items_to_append++ > 50 )
+ if( ++p_playlist_dialog->i_items_to_append >= 50 )
{
/* Too many items waiting to be added, it will be quicker to rebuild
* the whole playlist */