OSDN Git Service

RAD-471: Support for Group Bans
authorLatif Khalifa <latifer@streamgrid.net>
Sat, 15 Mar 2014 04:06:06 +0000 (05:06 +0100)
committerLatif Khalifa <latifer@streamgrid.net>
Sat, 15 Mar 2014 04:06:35 +0000 (05:06 +0100)
Radegast/GUI/Consoles/GroupDetails.Designer.cs
Radegast/GUI/Consoles/GroupDetails.cs
Radegast/GUI/Dialogs/BanGroupMember.Designer.cs [new file with mode: 0644]
Radegast/GUI/Dialogs/BanGroupMember.cs [new file with mode: 0644]
Radegast/GUI/Dialogs/BanGroupMember.resx [new file with mode: 0644]

index 610d5a1..4454a53 100644 (file)
@@ -156,10 +156,21 @@ namespace Radegast
             this.lblTitle = new System.Windows.Forms.Label();
             this.lblSentBy = new System.Windows.Forms.Label();
             this.label1 = new System.Windows.Forms.Label();
+            this.tpBanned = new System.Windows.Forms.TabPage();
+            this.lwBannedMembers = new Radegast.ListViewNoFlicker();
+            this.chBannedName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+            this.chBannedOn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+            this.pnlBannedBottom = new System.Windows.Forms.Panel();
+            this.btnRefreshBanned = new System.Windows.Forms.Button();
+            this.btnUnban = new System.Windows.Forms.Button();
+            this.btnBan = new System.Windows.Forms.Button();
+            this.pnlBannedTop = new System.Windows.Forms.Panel();
+            this.label9 = new System.Windows.Forms.Label();
             this.pnlBottomControls = new System.Windows.Forms.Panel();
             this.btnClose = new System.Windows.Forms.Button();
             this.btnApply = new System.Windows.Forms.Button();
             this.btnRefresh = new System.Windows.Forms.Button();
+            this.btnBanMember = new System.Windows.Forms.Button();
             this.tcGroupDetails.SuspendLayout();
             this.tpGeneral.SuspendLayout();
             this.memberListContextMenu.SuspendLayout();
@@ -178,6 +189,9 @@ namespace Radegast
             ((System.ComponentModel.ISupportInitialize)(this.icnNewNoticeAtt)).BeginInit();
             this.pnlArchivedNotice.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)(this.icnItem)).BeginInit();
+            this.tpBanned.SuspendLayout();
+            this.pnlBannedBottom.SuspendLayout();
+            this.pnlBannedTop.SuspendLayout();
             this.pnlBottomControls.SuspendLayout();
             this.SuspendLayout();
             // 
@@ -186,6 +200,7 @@ namespace Radegast
             this.tcGroupDetails.Controls.Add(this.tpGeneral);
             this.tcGroupDetails.Controls.Add(this.tpMembersRoles);
             this.tcGroupDetails.Controls.Add(this.tpNotices);
+            this.tcGroupDetails.Controls.Add(this.tpBanned);
             this.tcGroupDetails.Dock = System.Windows.Forms.DockStyle.Fill;
             this.tcGroupDetails.Location = new System.Drawing.Point(0, 0);
             this.tcGroupDetails.Name = "tcGroupDetails";
@@ -522,6 +537,7 @@ namespace Radegast
             this.panel1.Controls.Add(this.lvwAllowedAbilities);
             this.panel1.Controls.Add(this.lvwAssignedRoles);
             this.panel1.Controls.Add(this.btnInviteNewMember);
+            this.panel1.Controls.Add(this.btnBanMember);
             this.panel1.Controls.Add(this.btnEjectMember);
             this.panel1.Controls.Add(this.label3);
             this.panel1.Controls.Add(this.lblAssignedRoles);
@@ -577,24 +593,26 @@ namespace Radegast
             // 
             // btnInviteNewMember
             // 
+            this.btnInviteNewMember.AccessibleName = "Invite new member";
             this.btnInviteNewMember.Enabled = false;
             this.btnInviteNewMember.Location = new System.Drawing.Point(6, 3);
             this.btnInviteNewMember.Name = "btnInviteNewMember";
-            this.btnInviteNewMember.Size = new System.Drawing.Size(153, 23);
+            this.btnInviteNewMember.Size = new System.Drawing.Size(80, 23);
             this.btnInviteNewMember.TabIndex = 11;
-            this.btnInviteNewMember.Text = "Invite New Member...";
+            this.btnInviteNewMember.Text = "Invite";
             this.btnInviteNewMember.UseVisualStyleBackColor = true;
             this.btnInviteNewMember.Click += new System.EventHandler(this.btnInviteNewMember_Click);
             // 
             // btnEjectMember
             // 
+            this.btnEjectMember.AccessibleName = "Eject from group";
             this.btnEjectMember.Enabled = false;
-            this.btnEjectMember.Location = new System.Drawing.Point(221, 3);
+            this.btnEjectMember.Location = new System.Drawing.Point(92, 3);
             this.btnEjectMember.Name = "btnEjectMember";
-            this.btnEjectMember.Size = new System.Drawing.Size(153, 23);
+            this.btnEjectMember.Size = new System.Drawing.Size(80, 23);
             this.btnEjectMember.TabIndex = 11;
-            this.btnEjectMember.Text = "Eject From Group";
-            this.btnEjectMember.UseVisualStyleBackColor = true;
+            this.btnEjectMember.Text = "Eject";
+            this.btnEjectMember.UseVisualStyleBackColor = false;
             this.btnEjectMember.Click += new System.EventHandler(this.btnEjectMember_Click);
             // 
             // label3
@@ -1222,6 +1240,108 @@ namespace Radegast
             this.label1.Text = "Group Notice";
             this.label1.TextAlign = System.Drawing.ContentAlignment.TopRight;
             // 
+            // tpBanned
+            // 
+            this.tpBanned.Controls.Add(this.lwBannedMembers);
+            this.tpBanned.Controls.Add(this.pnlBannedBottom);
+            this.tpBanned.Controls.Add(this.pnlBannedTop);
+            this.tpBanned.Location = new System.Drawing.Point(4, 22);
+            this.tpBanned.Name = "tpBanned";
+            this.tpBanned.Size = new System.Drawing.Size(400, 439);
+            this.tpBanned.TabIndex = 4;
+            this.tpBanned.Text = "Banned Residents";
+            this.tpBanned.UseVisualStyleBackColor = true;
+            // 
+            // lwBannedMembers
+            // 
+            this.lwBannedMembers.AllowColumnReorder = true;
+            this.lwBannedMembers.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+            this.chBannedName,
+            this.chBannedOn});
+            this.lwBannedMembers.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.lwBannedMembers.FullRowSelect = true;
+            this.lwBannedMembers.GridLines = true;
+            this.lwBannedMembers.HideSelection = false;
+            this.lwBannedMembers.Location = new System.Drawing.Point(0, 28);
+            this.lwBannedMembers.Name = "lwBannedMembers";
+            this.lwBannedMembers.ShowGroups = false;
+            this.lwBannedMembers.Size = new System.Drawing.Size(400, 372);
+            this.lwBannedMembers.TabIndex = 10;
+            this.lwBannedMembers.UseCompatibleStateImageBehavior = false;
+            this.lwBannedMembers.View = System.Windows.Forms.View.Details;
+            this.lwBannedMembers.SelectedIndexChanged += new System.EventHandler(this.lwBannedMembers_SelectedIndexChanged);
+            // 
+            // chBannedName
+            // 
+            this.chBannedName.Text = "Resident name";
+            this.chBannedName.Width = 268;
+            // 
+            // chBannedOn
+            // 
+            this.chBannedOn.Text = "Banned on";
+            this.chBannedOn.Width = 90;
+            // 
+            // pnlBannedBottom
+            // 
+            this.pnlBannedBottom.Controls.Add(this.btnRefreshBanned);
+            this.pnlBannedBottom.Controls.Add(this.btnUnban);
+            this.pnlBannedBottom.Controls.Add(this.btnBan);
+            this.pnlBannedBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.pnlBannedBottom.Location = new System.Drawing.Point(0, 400);
+            this.pnlBannedBottom.Name = "pnlBannedBottom";
+            this.pnlBannedBottom.Size = new System.Drawing.Size(400, 39);
+            this.pnlBannedBottom.TabIndex = 4;
+            // 
+            // btnRefreshBanned
+            // 
+            this.btnRefreshBanned.Location = new System.Drawing.Point(165, 3);
+            this.btnRefreshBanned.Name = "btnRefreshBanned";
+            this.btnRefreshBanned.Size = new System.Drawing.Size(75, 23);
+            this.btnRefreshBanned.TabIndex = 2;
+            this.btnRefreshBanned.Text = "Refresh";
+            this.btnRefreshBanned.UseVisualStyleBackColor = true;
+            this.btnRefreshBanned.Click += new System.EventHandler(this.btnRefreshBanned_Click);
+            // 
+            // btnUnban
+            // 
+            this.btnUnban.Enabled = false;
+            this.btnUnban.Location = new System.Drawing.Point(84, 3);
+            this.btnUnban.Name = "btnUnban";
+            this.btnUnban.Size = new System.Drawing.Size(75, 23);
+            this.btnUnban.TabIndex = 1;
+            this.btnUnban.Text = "Unban";
+            this.btnUnban.UseVisualStyleBackColor = true;
+            this.btnUnban.Click += new System.EventHandler(this.btnUnban_Click);
+            // 
+            // btnBan
+            // 
+            this.btnBan.Location = new System.Drawing.Point(3, 3);
+            this.btnBan.Name = "btnBan";
+            this.btnBan.Size = new System.Drawing.Size(75, 23);
+            this.btnBan.TabIndex = 0;
+            this.btnBan.Text = "Ban...";
+            this.btnBan.UseVisualStyleBackColor = true;
+            this.btnBan.Click += new System.EventHandler(this.btnBan_Click);
+            // 
+            // pnlBannedTop
+            // 
+            this.pnlBannedTop.Controls.Add(this.label9);
+            this.pnlBannedTop.Dock = System.Windows.Forms.DockStyle.Top;
+            this.pnlBannedTop.Location = new System.Drawing.Point(0, 0);
+            this.pnlBannedTop.Name = "pnlBannedTop";
+            this.pnlBannedTop.Size = new System.Drawing.Size(400, 28);
+            this.pnlBannedTop.TabIndex = 3;
+            // 
+            // label9
+            // 
+            this.label9.AutoSize = true;
+            this.label9.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label9.Location = new System.Drawing.Point(3, 3);
+            this.label9.Name = "label9";
+            this.label9.Size = new System.Drawing.Size(222, 17);
+            this.label9.TabIndex = 2;
+            this.label9.Text = "Residents banned from this group";
+            // 
             // pnlBottomControls
             // 
             this.pnlBottomControls.Controls.Add(this.btnClose);
@@ -1266,6 +1386,18 @@ namespace Radegast
             this.btnRefresh.UseVisualStyleBackColor = true;
             this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
             // 
+            // btnBanMember
+            // 
+            this.btnBanMember.AccessibleName = "Eject from group";
+            this.btnBanMember.Enabled = false;
+            this.btnBanMember.Location = new System.Drawing.Point(178, 3);
+            this.btnBanMember.Name = "btnBanMember";
+            this.btnBanMember.Size = new System.Drawing.Size(80, 23);
+            this.btnBanMember.TabIndex = 11;
+            this.btnBanMember.Text = "Ban";
+            this.btnBanMember.UseVisualStyleBackColor = false;
+            this.btnBanMember.Click += new System.EventHandler(this.btnBanMember_Click);
+            // 
             // GroupDetails
             // 
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
@@ -1301,6 +1433,10 @@ namespace Radegast
             this.pnlArchivedNotice.ResumeLayout(false);
             this.pnlArchivedNotice.PerformLayout();
             ((System.ComponentModel.ISupportInitialize)(this.icnItem)).EndInit();
+            this.tpBanned.ResumeLayout(false);
+            this.pnlBannedBottom.ResumeLayout(false);
+            this.pnlBannedTop.ResumeLayout(false);
+            this.pnlBannedTop.PerformLayout();
             this.pnlBottomControls.ResumeLayout(false);
             this.ResumeLayout(false);
 
@@ -1408,6 +1544,17 @@ namespace Radegast
         private System.Windows.Forms.ColumnHeader cbRoleID;
         private System.Windows.Forms.ContextMenuStrip rolesContextMenu;
         private System.Windows.Forms.ToolStripMenuItem copyRoleIDToolStripMenuItem;
+        private System.Windows.Forms.TabPage tpBanned;
+        public ListViewNoFlicker lwBannedMembers;
+        public System.Windows.Forms.ColumnHeader chBannedName;
+        public System.Windows.Forms.ColumnHeader chBannedOn;
+        private System.Windows.Forms.Panel pnlBannedBottom;
+        private System.Windows.Forms.Button btnRefreshBanned;
+        private System.Windows.Forms.Button btnUnban;
+        private System.Windows.Forms.Button btnBan;
+        private System.Windows.Forms.Panel pnlBannedTop;
+        public System.Windows.Forms.Label label9;
+        public System.Windows.Forms.Button btnBanMember;
 
     }
 }
index 4a20ee2..fa1ce72 100644 (file)
@@ -88,6 +88,11 @@ namespace Radegast
             {
                 tcGroupDetails.TabPages.Remove(tpMembersRoles);
                 tcGroupDetails.TabPages.Remove(tpNotices);
+                tcGroupDetails.TabPages.Remove(tpBanned);
+            }
+            else
+            {
+                RefreshBans();
             }
 
             lvwNoticeArchive.SmallImageList = frmMain.ResourceImages;
@@ -110,7 +115,6 @@ namespace Radegast
             RefreshGroupInfo();
         }
 
-
         void GroupDetails_Disposed(object sender, EventArgs e)
         {
             client.Groups.GroupTitlesReply -= new EventHandler<GroupTitlesReplyEventArgs>(Groups_GroupTitlesReply);
@@ -729,6 +733,10 @@ namespace Radegast
                 case "tpMembersRoles":
                     RefreshMembersRoles();
                     break;
+
+                case "tpBanned":
+                    RefreshBans();
+                    break;
             }
         }
 
@@ -805,6 +813,8 @@ namespace Radegast
 
         private void lvwMemberDetails_SelectedIndexChanged(object sender, EventArgs e)
         {
+            btnBanMember.Enabled = lvwMemberDetails.SelectedIndices.Count > 0;
+
             if (lvwMemberDetails.SelectedIndices.Count != 1 || roles == null || roleMembers == null) return;
             EnhancedGroupMember m = GroupMembers[lvwMemberDetails.SelectedIndices[0]];
 
@@ -1229,6 +1239,97 @@ namespace Radegast
             }
         }
 
+        #region Group Bans
+        public void RefreshBans()
+        {
+            client.Groups.RequestBannedAgents(group.ID, (xs, xe) =>
+            {
+                UpdateBannedAgents(xe);
+            });
+        }
+
+        void UpdateBannedAgents(BannedAgentsEventArgs e)
+        {
+            if (!e.Success || e.GroupID != group.ID) return;
+            if (InvokeRequired)
+            {
+                BeginInvoke(new MethodInvoker(() => UpdateBannedAgents(e)));
+                return;
+            }
+
+            lwBannedMembers.BeginUpdate();
+            lwBannedMembers.Items.Clear();
+
+            foreach (var member in e.BannedAgents)
+            {
+                var item = new ListViewItem(instance.Names.Get(member.Key));
+                item.Name = member.Key.ToString();
+                item.SubItems.Add(member.Value.ToShortDateString());
+                lwBannedMembers.Items.Add(item);
+            }
+            lwBannedMembers.EndUpdate();
+        }
+
+        private void btnBan_Click(object sender, EventArgs e)
+        {
+            (new BanGroupMember(instance, group, this)).Show();
+        }
+
+        private void btnUnban_Click(object sender, EventArgs e)
+        {
+            List<UUID> toUnban = new List<UUID>();
+            for (int i=0; i<lwBannedMembers.SelectedItems.Count; i++)
+            {
+                UUID id;
+                if (UUID.TryParse(lwBannedMembers.SelectedItems[i].Name, out id))
+                {
+                    toUnban.Add(id);
+                }
+            }
+
+            if (toUnban.Count > 0)
+            {
+                client.Groups.RequestBanAction(group.ID, GroupBanAction.Unban, toUnban.ToArray(), (xs, se) =>
+                {
+                    RefreshBans();
+                });
+            }
+        }
+
+        private void btnRefreshBanned_Click(object sender, EventArgs e)
+        {
+            RefreshBans();
+        }
+
+        private void lwBannedMembers_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            btnUnban.Enabled = lwBannedMembers.SelectedItems.Count > 0;
+        }
+
+        private void btnBanMember_Click(object sender, EventArgs e)
+        {
+            try
+            {
+                List<UUID> toBan = new List<UUID>();
+                for (int i = 0; i < lvwMemberDetails.SelectedIndices.Count; i++)
+                {
+                    EnhancedGroupMember m = GroupMembers[lvwMemberDetails.SelectedIndices[i]];
+                    toBan.Add(m.Base.ID);
+                    client.Groups.EjectUser(group.ID, m.Base.ID);
+                }
+
+                if (toBan.Count > 0)
+                {
+                    client.Groups.RequestBanAction(group.ID, GroupBanAction.Ban, toBan.ToArray(), (xs, xe) =>
+                    {
+                        RefreshBans();
+                    });
+                }
+            }
+            catch { }
+
+        }
+        #endregion Group Bans
     }
 
     public class EnhancedGroupMember
diff --git a/Radegast/GUI/Dialogs/BanGroupMember.Designer.cs b/Radegast/GUI/Dialogs/BanGroupMember.Designer.cs
new file mode 100644 (file)
index 0000000..c6928a9
--- /dev/null
@@ -0,0 +1,112 @@
+// 
+// Radegast Metaverse Client
+// Copyright (c) 2009-2014, Radegast Development Team
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//     * Redistributions of source code must retain the above copyright notice,
+//       this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of the application "Radegast", nor the names of its
+//       contributors may be used to endorse or promote products derived from
+//       this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// $Id$
+//
+namespace Radegast
+{
+    partial class BanGroupMember
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BanGroupMember));
+            this.pnlInvite = new System.Windows.Forms.Panel();
+            this.btnBan = new System.Windows.Forms.Button();
+            this.pnlInvite.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // pnlInvite
+            // 
+            this.pnlInvite.Controls.Add(this.btnBan);
+            this.pnlInvite.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.pnlInvite.Location = new System.Drawing.Point(0, 338);
+            this.pnlInvite.Name = "pnlInvite";
+            this.pnlInvite.Size = new System.Drawing.Size(330, 31);
+            this.pnlInvite.TabIndex = 0;
+            // 
+            // btnBan
+            // 
+            this.btnBan.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnBan.Enabled = false;
+            this.btnBan.Location = new System.Drawing.Point(201, 5);
+            this.btnBan.Name = "btnBan";
+            this.btnBan.Size = new System.Drawing.Size(117, 23);
+            this.btnBan.TabIndex = 1;
+            this.btnBan.Text = "Ban";
+            this.btnBan.UseVisualStyleBackColor = true;
+            this.btnBan.Click += new System.EventHandler(this.btnIvite_Click);
+            // 
+            // BanGroupMember
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(330, 369);
+            this.Controls.Add(this.pnlInvite);
+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+            this.MaximizeBox = false;
+            this.MinimizeBox = false;
+            this.Name = "BanGroupMember";
+            this.Text = "Select resident";
+            this.Load += new System.EventHandler(this.GroupInvite_Load);
+            this.pnlInvite.ResumeLayout(false);
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Panel pnlInvite;
+        private System.Windows.Forms.Button btnBan;
+
+
+    }
+}
\ No newline at end of file
diff --git a/Radegast/GUI/Dialogs/BanGroupMember.cs b/Radegast/GUI/Dialogs/BanGroupMember.cs
new file mode 100644 (file)
index 0000000..8d5a63a
--- /dev/null
@@ -0,0 +1,121 @@
+// 
+// Radegast Metaverse Client
+// Copyright (c) 2009-2014, Radegast Development Team
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//     * Redistributions of source code must retain the above copyright notice,
+//       this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of the application "Radegast", nor the names of its
+//       contributors may be used to endorse or promote products derived from
+//       this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// $Id$
+//
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using OpenMetaverse;
+
+namespace Radegast
+{
+    public partial class BanGroupMember : RadegastForm
+    {
+        AvatarPicker picker;
+        RadegastInstance instance;
+        Netcom.RadegastNetcom netcom;
+        GroupDetails parent;
+
+        Group group;
+
+        public BanGroupMember(RadegastInstance instance, Group group, GroupDetails parent)
+            :base(instance)
+        {
+            InitializeComponent();
+            Disposed += new EventHandler(GroupInvite_Disposed);
+            AutoSavePosition = true;
+
+            this.instance = instance;
+            this.group = group;
+            this.netcom = instance.Netcom;
+            this.parent = parent;
+
+            picker = new AvatarPicker(instance) { Dock = DockStyle.Fill };
+            Controls.Add(picker);
+            picker.SelectionChaged += new EventHandler(picker_SelectionChaged);
+            picker.BringToFront();
+            
+            netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(Netcom_ClientDisconnected);
+        }
+
+        void picker_SelectionChaged(object sender, EventArgs e)
+        {
+            btnBan.Enabled = picker.SelectedAvatars.Count > 0;
+        }
+
+        void GroupInvite_Disposed(object sender, EventArgs e)
+        {
+            netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(Netcom_ClientDisconnected);
+            netcom = null;
+            instance = null;
+            picker.Dispose();
+            Logger.DebugLog("Group picker disposed");
+        }
+
+        void Netcom_ClientDisconnected(object sender, OpenMetaverse.DisconnectedEventArgs e)
+        {
+            ((Radegast.Netcom.RadegastNetcom)sender).ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(Netcom_ClientDisconnected);
+
+            if (!instance.MonoRuntime || IsHandleCreated)
+                BeginInvoke(new MethodInvoker(() =>
+                {
+                    Close();
+                }
+                ));
+        }
+
+
+        private void GroupInvite_Load(object sender, EventArgs e)
+        {
+            picker.txtSearch.Focus();
+        }
+
+        private void btnIvite_Click(object sender, EventArgs e)
+        {
+            List<UUID> toBan = new List<UUID>();
+            foreach (UUID key in picker.SelectedAvatars.Keys)
+            {
+                toBan.Add(key);
+            }
+            if (toBan.Count > 0)
+            {
+                Client.Groups.RequestBanAction(group.ID, GroupBanAction.Ban, toBan.ToArray(), (xs, xe) =>
+                {
+                    parent.RefreshBans();
+                });
+            }
+            Close();
+        }
+    }
+}
diff --git a/Radegast/GUI/Dialogs/BanGroupMember.resx b/Radegast/GUI/Dialogs/BanGroupMember.resx
new file mode 100644 (file)
index 0000000..78fa81c
--- /dev/null
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+        AAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+        AAEAAAABAAAAAQAAAAHCmW8HPUFD/ygrKwcAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAB/ceQ+f/I
+        kf89QUP9AAAAAQAAAAHuu4dX/8iR/z1BQ/89QUP/PUFD/z1BQ/84PD1BAAAAAeu5hkn/yJH//8iR///I
+        kf//yJH/PUFD/z1BQ/86PkCB/8iR///Ikf89QUP/PUFD/z1BQ/89QUP/PUFD/0VGRv//yJH//8iR///I
+        kf//yJH//8iR/z1BQ/89QUP/PUFD///Ikf//yJH/PUFD/z1BQ/89QUP/PUFD/z1BQ/9FRkb//8iR///I
+        kf//yJH//8iR///Ikf89QUP/PUFD/z1BQ///yJH//8iR/z1BQ/89QUP/PUFD/z1BQ/89QUP/RUZG///I
+        kf//yJH//8iR///Ikf//yJH/PUFD/z1BQ/89QUP//8iR///Ikf89QUP/PUFD/z1BQ/89QUP/PUFD/0VG
+        Rv//yJH//8iR///Ikf//yJH//8iR/z1BQ/89QUP/PUFD///Ikf//yJH/PUFD/z1BQ/89QUP/PUFD/z1B
+        Q/9FRkb//8iR///Ikf//yJH//8iR///Ikf89QUP/PUFD/z1BQ//3woyR98KMkTs/QZE7P0GROz9BkZF8
+        Zf+RfGX/knxl/6qNb/+qjW//qo1v//fCjJH3woyROz9BkTs/QZE7P0GRAAAAAQAAAAEAAAABAAAAAQAA
+        AAH/yJH//8iR//fCjv89QUP/PUFD/z1BQ/8AAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+        AAEAAAAB/8iR///Ikf/3wo7/PUFD/z1BQ/89QUP/AAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+        AAEAAAABAAAAAf/Ikf//yJH/98KO/z1BQ/89QUP/PUFD/wAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+        AAEAAAABAAAAAQAAAAH/yJH//8iR//fCjv89QUP/PUFD/z1BQ/8AAAABAAAAAQAAAAEAAAABAAAAAQAA
+        AAEAAAABAAAAAQAAAAEAAAABAAAAAf/Ikf/3wo7/PUFD/zs/Qa8AAAABAAAAAQAAAAEAAAABAAAAAQAA
+        AAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+        AAEAAAABAAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA
+        //8AAP//AAD//w==
+</value>
+  </data>
+</root>
\ No newline at end of file