We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Wx BitmapFromBufferRGBA deprecated in favor of Bitmap.FromBufferRGBA
```
c:\users\rporuri\work\github\ets\chaco\chaco\tools\toolbars\toolbar_buttons.py:190: wxPyDeprecationWarning: Call to deprecated item BitmapFromBufferRGBA. Use :meth:`wx.Bitmap.FromBufferRGBA` instead.
  width + 1, height + 1, gc.bmp_array.flatten()
```

Discovered when running `examples/demo/depth.py`

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `chaco/tools/toolbars/toolbar_buttons.py`
Content:
```
1 # (C) Copyright 2005-2021 Enthought, Inc., Austin, TX
2 # All rights reserved.
3 #
4 # This software is provided without warranty under the terms of the BSD
5 # license included in LICENSE.txt and may be redistributed only under
6 # the conditions described in the aforementioned license. The license
7 # is also available online at http://www.enthought.com/licenses/BSD.txt
8 #
9 # Thanks for using Enthought open source!
10 
11 import numpy
12 
13 from traits.etsconfig.api import ETSConfig
14 from enable.tools.toolbars.toolbar_buttons import Button
15 from chaco.tools.zoom_tool import ZoomTool
16 from chaco.plot_graphics_context import PlotGraphicsContext
17 from kiva.image import Image
18 from pyface.image_resource import ImageResource
19 from pyface.api import FileDialog, OK, error
20 from traits.api import (
21     Instance,
22     Str,
23     Property,
24     cached_property,
25     List,
26     Int,
27     Enum,
28 )
29 
30 
31 class ToolbarButton(Button):
32     image = Str()
33     _image = Instance(Image)
34 
35     color = "black"
36 
37     width = Property(Int, observe="label, image")
38     height = Property(Int, observe="label, image")
39 
40     # bounds are used for hit testing
41     bounds = Property(List, observe="label, image")
42 
43     def __init__(self, *args, **kw):
44         super().__init__(*args, **kw)
45 
46         image_resource = ImageResource(self.image)
47         self._image = Image(image_resource.absolute_path)
48 
49     @cached_property
50     def _get_width(self):
51         gc = PlotGraphicsContext((100, 100), dpi=72)
52         gc.set_font(self.label_font)
53         (w, h, descent, leading) = gc.get_full_text_extent(self.label)
54         return max(self._image.width(), w)
55 
56     @cached_property
57     def _get_height(self):
58         gc = PlotGraphicsContext((100, 100), dpi=72)
59         gc.set_font(self.label_font)
60         (w, h, descent, leading) = gc.get_full_text_extent(self.label)
61         return self._image.height() + h
62 
63     @cached_property
64     def _get_bounds(self):
65         return [self.width, self.height]
66 
67     def _draw_actual_button(self, gc):
68         x_offset = self.x + (self.width - self._image.width()) / 2
69         gc.draw_image(
70             self._image,
71             (x_offset, self.y + 2, self._image.width(), self._image.height()),
72         )
73 
74         if self.label is not None and len(self.label) > 0:
75             gc.set_font(self.label_font)
76 
77             (w, h, descent, leading) = gc.get_full_text_extent(self.label)
78             if w < self.width:
79                 x_offset = self.x + (self.width - w) / 2
80             else:
81                 x_offset = self.x
82 
83             gc.set_text_position(x_offset, self.y - 8)
84             gc.show_text(self.label)
85 
86 
87 class IndexAxisLogButton(ToolbarButton):
88     label = "X Log Scale"
89     tooltip = "Change index axis scale"
90     image = "zoom-fit-width"
91 
92     def perform(self, event):
93         if self.container.component.index_scale == "linear":
94             self.container.component.index_scale = "log"
95         else:
96             self.container.component.index_scale = "linear"
97         self.container.request_redraw()
98 
99 
100 class ValueAxisLogButton(ToolbarButton):
101     label = "Y Log Scale"
102     tooltip = "Change value axis scale"
103     image = "zoom-fit-height"
104 
105     def perform(self, event):
106         if self.container.component.value_scale == "linear":
107             self.container.component.value_scale = "log"
108         else:
109             self.container.component.value_scale = "linear"
110         self.container.request_redraw()
111 
112 
113 class ZoomResetButton(ToolbarButton):
114     label = "Zoom Reset"
115     tooltip = "Zoom Reset"
116     image = "zoom-original"
117 
118     def perform(self, event):
119         plot_component = self.container.component
120 
121         for overlay in plot_component.overlays:
122             if isinstance(overlay, ZoomTool):
123                 overlay._reset_state_pressed()
124 
125         self.container.request_redraw()
126 
127 
128 class SaveAsButton(ToolbarButton):
129     label = "Save As"
130     tooltip = "Save As"
131     image = "document-save"
132 
133     def perform(self, event):
134 
135         plot_component = self.container.component
136 
137         filter = "PNG file (*.png)|*.png|\nTIFF file (*.tiff)|*.tiff|"
138         dialog = FileDialog(action="save as", wildcard=filter)
139 
140         if dialog.open() != OK:
141             return
142 
143         # Remove the toolbar before saving the plot, so the output doesn't
144         # include the toolbar.
145         plot_component.remove_toolbar()
146 
147         filename = dialog.path
148 
149         width, height = plot_component.outer_bounds
150 
151         gc = PlotGraphicsContext((width, height), dpi=72)
152         gc.render_component(plot_component)
153         try:
154             gc.save(filename)
155         except KeyError as e:
156             errmsg = (
157                 "The filename must have an extension that matches "
158                 "a graphics format, such as '.png' or '.tiff'."
159             )
160             if str(e.message) != "":
161                 errmsg = (
162                     "Unknown filename extension: '%s'\n" % str(e.message)
163                 ) + errmsg
164 
165             error(None, errmsg, title="Invalid Filename Extension")
166 
167         # Restore the toolbar.
168         plot_component.add_toolbar()
169 
170 
171 class CopyToClipboardButton(ToolbarButton):
172     label = "Copy Image"
173     tooltip = "Copy to the clipboard"
174     image = "edit-copy"
175 
176     def perform(self, event):
177         plot_component = self.container.component
178 
179         # Remove the toolbar before saving the plot, so the output doesn't
180         # include the toolbar.
181         plot_component.remove_toolbar()
182 
183         width, height = plot_component.outer_bounds
184 
185         gc = PlotGraphicsContext((width, height), dpi=72)
186         gc.render_component(plot_component)
187 
188         if ETSConfig.toolkit == "wx":
189             self._perform_wx(width, height, gc)
190         else:
191             pass
192 
193         # Restore the toolbar.
194         plot_component.add_toolbar()
195 
196     def _perform_wx(self, width, height, gc):
197         import wx
198 
199         bitmap = wx.BitmapFromBufferRGBA(
200             width + 1, height + 1, gc.bmp_array.flatten()
201         )
202         data = wx.BitmapDataObject()
203         data.SetBitmap(bitmap)
204         if wx.TheClipboard.Open():
205             wx.TheClipboard.SetData(data)
206             wx.TheClipboard.Close()
207         else:
208             wx.MessageBox("Unable to open the clipboard.", "Error")
209 
210 
211 class ExportDataToClipboardButton(ToolbarButton):
212     label = "Copy Data"
213     tooltip = "Copy data to the clipboard"
214     image = "application-vnd-ms-excel"
215 
216     orientation = Enum("v", "h")
217 
218     def perform(self, event):
219         if ETSConfig.toolkit == "wx":
220             self._perform_wx()
221         elif ETSConfig.toolkit == "qt4":
222             self._perform_qt()
223         else:
224             pass
225 
226     def _get_data_from_plots(self):
227         values = []
228         indices = []
229         for renderers in self.container.component.plots.values():
230             for renderer in renderers:
231                 indices.append(renderer.index.get_data())
232                 values.append(renderer.value.get_data())
233         return indices, values
234 
235     def _serialize_data(self, indices, values):
236 
237         # if all of rows are the same length, use faster algorithms,
238         # otherwise go element by element adding the necessary empty strings
239         if len(set([len(l) for l in values])) == 1:
240             data = [indices[0]] + values
241             if self.orientation == "v":
242                 data = numpy.array(data).T.tolist()
243 
244             data_str = ""
245             for row in data:
246                 data_str += ",".join(["%f" % v for v in row]) + "\n"
247             return data_str
248 
249         else:
250             # There might not be a single solution which fits all cases,
251             # so this is left to specific implementations to override
252             raise NotImplementedError()
253 
254     def _perform_wx(self):
255         import wx
256 
257         indices, values = self._get_data_from_plots()
258         data_str = self._serialize_data(indices, values)
259         data_obj = wx.TextDataObject(data_str)
260 
261         if wx.TheClipboard.Open():
262             wx.TheClipboard.SetData(data_obj)
263             wx.TheClipboard.Close()
264         else:
265             wx.MessageBox("Unable to open the clipboard.", "Error")
266 
267     def _perform_qt(self):
268         from pyface.qt import QtGui
269 
270         indices, values = self._get_data_from_plots()
271         data_str = self._serialize_data(indices, values)
272 
273         QtGui.QApplication.clipboard().setText(data_str)
274
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/chaco/tools/toolbars/toolbar_buttons.py b/chaco/tools/toolbars/toolbar_buttons.py
--- a/chaco/tools/toolbars/toolbar_buttons.py
+++ b/chaco/tools/toolbars/toolbar_buttons.py
@@ -196,7 +196,7 @@
     def _perform_wx(self, width, height, gc):
         import wx
 
-        bitmap = wx.BitmapFromBufferRGBA(
+        bitmap = wx.Bitmap.FromBufferRGBA(
             width + 1, height + 1, gc.bmp_array.flatten()
         )
         data = wx.BitmapDataObject()

{"golden_diff": "diff --git a/chaco/tools/toolbars/toolbar_buttons.py b/chaco/tools/toolbars/toolbar_buttons.py\n--- a/chaco/tools/toolbars/toolbar_buttons.py\n+++ b/chaco/tools/toolbars/toolbar_buttons.py\n@@ -196,7 +196,7 @@\n     def _perform_wx(self, width, height, gc):\n         import wx\n \n-        bitmap = wx.BitmapFromBufferRGBA(\n+        bitmap = wx.Bitmap.FromBufferRGBA(\n             width + 1, height + 1, gc.bmp_array.flatten()\n         )\n         data = wx.BitmapDataObject()\n", "issue": "Wx BitmapFromBufferRGBA deprecated in favor of Bitmap.FromBufferRGBA\n```\r\nc:\\users\\rporuri\\work\\github\\ets\\chaco\\chaco\\tools\\toolbars\\toolbar_buttons.py:190: wxPyDeprecationWarning: Call to deprecated item BitmapFromBufferRGBA. Use :meth:`wx.Bitmap.FromBufferRGBA` instead.\r\n  width + 1, height + 1, gc.bmp_array.flatten()\r\n```\r\n\r\nDiscovered when running `examples/demo/depth.py`\n", "before_files": [{"content": "# (C) Copyright 2005-2021 Enthought, Inc., Austin, TX\n# All rights reserved.\n#\n# This software is provided without warranty under the terms of the BSD\n# license included in LICENSE.txt and may be redistributed only under\n# the conditions described in the aforementioned license. The license\n# is also available online at http://www.enthought.com/licenses/BSD.txt\n#\n# Thanks for using Enthought open source!\n\nimport numpy\n\nfrom traits.etsconfig.api import ETSConfig\nfrom enable.tools.toolbars.toolbar_buttons import Button\nfrom chaco.tools.zoom_tool import ZoomTool\nfrom chaco.plot_graphics_context import PlotGraphicsContext\nfrom kiva.image import Image\nfrom pyface.image_resource import ImageResource\nfrom pyface.api import FileDialog, OK, error\nfrom traits.api import (\n    Instance,\n    Str,\n    Property,\n    cached_property,\n    List,\n    Int,\n    Enum,\n)\n\n\nclass ToolbarButton(Button):\n    image = Str()\n    _image = Instance(Image)\n\n    color = \"black\"\n\n    width = Property(Int, observe=\"label, image\")\n    height = Property(Int, observe=\"label, image\")\n\n    # bounds are used for hit testing\n    bounds = Property(List, observe=\"label, image\")\n\n    def __init__(self, *args, **kw):\n        super().__init__(*args, **kw)\n\n        image_resource = ImageResource(self.image)\n        self._image = Image(image_resource.absolute_path)\n\n    @cached_property\n    def _get_width(self):\n        gc = PlotGraphicsContext((100, 100), dpi=72)\n        gc.set_font(self.label_font)\n        (w, h, descent, leading) = gc.get_full_text_extent(self.label)\n        return max(self._image.width(), w)\n\n    @cached_property\n    def _get_height(self):\n        gc = PlotGraphicsContext((100, 100), dpi=72)\n        gc.set_font(self.label_font)\n        (w, h, descent, leading) = gc.get_full_text_extent(self.label)\n        return self._image.height() + h\n\n    @cached_property\n    def _get_bounds(self):\n        return [self.width, self.height]\n\n    def _draw_actual_button(self, gc):\n        x_offset = self.x + (self.width - self._image.width()) / 2\n        gc.draw_image(\n            self._image,\n            (x_offset, self.y + 2, self._image.width(), self._image.height()),\n        )\n\n        if self.label is not None and len(self.label) > 0:\n            gc.set_font(self.label_font)\n\n            (w, h, descent, leading) = gc.get_full_text_extent(self.label)\n            if w < self.width:\n                x_offset = self.x + (self.width - w) / 2\n            else:\n                x_offset = self.x\n\n            gc.set_text_position(x_offset, self.y - 8)\n            gc.show_text(self.label)\n\n\nclass IndexAxisLogButton(ToolbarButton):\n    label = \"X Log Scale\"\n    tooltip = \"Change index axis scale\"\n    image = \"zoom-fit-width\"\n\n    def perform(self, event):\n        if self.container.component.index_scale == \"linear\":\n            self.container.component.index_scale = \"log\"\n        else:\n            self.container.component.index_scale = \"linear\"\n        self.container.request_redraw()\n\n\nclass ValueAxisLogButton(ToolbarButton):\n    label = \"Y Log Scale\"\n    tooltip = \"Change value axis scale\"\n    image = \"zoom-fit-height\"\n\n    def perform(self, event):\n        if self.container.component.value_scale == \"linear\":\n            self.container.component.value_scale = \"log\"\n        else:\n            self.container.component.value_scale = \"linear\"\n        self.container.request_redraw()\n\n\nclass ZoomResetButton(ToolbarButton):\n    label = \"Zoom Reset\"\n    tooltip = \"Zoom Reset\"\n    image = \"zoom-original\"\n\n    def perform(self, event):\n        plot_component = self.container.component\n\n        for overlay in plot_component.overlays:\n            if isinstance(overlay, ZoomTool):\n                overlay._reset_state_pressed()\n\n        self.container.request_redraw()\n\n\nclass SaveAsButton(ToolbarButton):\n    label = \"Save As\"\n    tooltip = \"Save As\"\n    image = \"document-save\"\n\n    def perform(self, event):\n\n        plot_component = self.container.component\n\n        filter = \"PNG file (*.png)|*.png|\\nTIFF file (*.tiff)|*.tiff|\"\n        dialog = FileDialog(action=\"save as\", wildcard=filter)\n\n        if dialog.open() != OK:\n            return\n\n        # Remove the toolbar before saving the plot, so the output doesn't\n        # include the toolbar.\n        plot_component.remove_toolbar()\n\n        filename = dialog.path\n\n        width, height = plot_component.outer_bounds\n\n        gc = PlotGraphicsContext((width, height), dpi=72)\n        gc.render_component(plot_component)\n        try:\n            gc.save(filename)\n        except KeyError as e:\n            errmsg = (\n                \"The filename must have an extension that matches \"\n                \"a graphics format, such as '.png' or '.tiff'.\"\n            )\n            if str(e.message) != \"\":\n                errmsg = (\n                    \"Unknown filename extension: '%s'\\n\" % str(e.message)\n                ) + errmsg\n\n            error(None, errmsg, title=\"Invalid Filename Extension\")\n\n        # Restore the toolbar.\n        plot_component.add_toolbar()\n\n\nclass CopyToClipboardButton(ToolbarButton):\n    label = \"Copy Image\"\n    tooltip = \"Copy to the clipboard\"\n    image = \"edit-copy\"\n\n    def perform(self, event):\n        plot_component = self.container.component\n\n        # Remove the toolbar before saving the plot, so the output doesn't\n        # include the toolbar.\n        plot_component.remove_toolbar()\n\n        width, height = plot_component.outer_bounds\n\n        gc = PlotGraphicsContext((width, height), dpi=72)\n        gc.render_component(plot_component)\n\n        if ETSConfig.toolkit == \"wx\":\n            self._perform_wx(width, height, gc)\n        else:\n            pass\n\n        # Restore the toolbar.\n        plot_component.add_toolbar()\n\n    def _perform_wx(self, width, height, gc):\n        import wx\n\n        bitmap = wx.BitmapFromBufferRGBA(\n            width + 1, height + 1, gc.bmp_array.flatten()\n        )\n        data = wx.BitmapDataObject()\n        data.SetBitmap(bitmap)\n        if wx.TheClipboard.Open():\n            wx.TheClipboard.SetData(data)\n            wx.TheClipboard.Close()\n        else:\n            wx.MessageBox(\"Unable to open the clipboard.\", \"Error\")\n\n\nclass ExportDataToClipboardButton(ToolbarButton):\n    label = \"Copy Data\"\n    tooltip = \"Copy data to the clipboard\"\n    image = \"application-vnd-ms-excel\"\n\n    orientation = Enum(\"v\", \"h\")\n\n    def perform(self, event):\n        if ETSConfig.toolkit == \"wx\":\n            self._perform_wx()\n        elif ETSConfig.toolkit == \"qt4\":\n            self._perform_qt()\n        else:\n            pass\n\n    def _get_data_from_plots(self):\n        values = []\n        indices = []\n        for renderers in self.container.component.plots.values():\n            for renderer in renderers:\n                indices.append(renderer.index.get_data())\n                values.append(renderer.value.get_data())\n        return indices, values\n\n    def _serialize_data(self, indices, values):\n\n        # if all of rows are the same length, use faster algorithms,\n        # otherwise go element by element adding the necessary empty strings\n        if len(set([len(l) for l in values])) == 1:\n            data = [indices[0]] + values\n            if self.orientation == \"v\":\n                data = numpy.array(data).T.tolist()\n\n            data_str = \"\"\n            for row in data:\n                data_str += \",\".join([\"%f\" % v for v in row]) + \"\\n\"\n            return data_str\n\n        else:\n            # There might not be a single solution which fits all cases,\n            # so this is left to specific implementations to override\n            raise NotImplementedError()\n\n    def _perform_wx(self):\n        import wx\n\n        indices, values = self._get_data_from_plots()\n        data_str = self._serialize_data(indices, values)\n        data_obj = wx.TextDataObject(data_str)\n\n        if wx.TheClipboard.Open():\n            wx.TheClipboard.SetData(data_obj)\n            wx.TheClipboard.Close()\n        else:\n            wx.MessageBox(\"Unable to open the clipboard.\", \"Error\")\n\n    def _perform_qt(self):\n        from pyface.qt import QtGui\n\n        indices, values = self._get_data_from_plots()\n        data_str = self._serialize_data(indices, values)\n\n        QtGui.QApplication.clipboard().setText(data_str)\n", "path": "chaco/tools/toolbars/toolbar_buttons.py"}], "after_files": [{"content": "# (C) Copyright 2005-2021 Enthought, Inc., Austin, TX\n# All rights reserved.\n#\n# This software is provided without warranty under the terms of the BSD\n# license included in LICENSE.txt and may be redistributed only under\n# the conditions described in the aforementioned license. The license\n# is also available online at http://www.enthought.com/licenses/BSD.txt\n#\n# Thanks for using Enthought open source!\n\nimport numpy\n\nfrom traits.etsconfig.api import ETSConfig\nfrom enable.tools.toolbars.toolbar_buttons import Button\nfrom chaco.tools.zoom_tool import ZoomTool\nfrom chaco.plot_graphics_context import PlotGraphicsContext\nfrom kiva.image import Image\nfrom pyface.image_resource import ImageResource\nfrom pyface.api import FileDialog, OK, error\nfrom traits.api import (\n    Instance,\n    Str,\n    Property,\n    cached_property,\n    List,\n    Int,\n    Enum,\n)\n\n\nclass ToolbarButton(Button):\n    image = Str()\n    _image = Instance(Image)\n\n    color = \"black\"\n\n    width = Property(Int, observe=\"label, image\")\n    height = Property(Int, observe=\"label, image\")\n\n    # bounds are used for hit testing\n    bounds = Property(List, observe=\"label, image\")\n\n    def __init__(self, *args, **kw):\n        super().__init__(*args, **kw)\n\n        image_resource = ImageResource(self.image)\n        self._image = Image(image_resource.absolute_path)\n\n    @cached_property\n    def _get_width(self):\n        gc = PlotGraphicsContext((100, 100), dpi=72)\n        gc.set_font(self.label_font)\n        (w, h, descent, leading) = gc.get_full_text_extent(self.label)\n        return max(self._image.width(), w)\n\n    @cached_property\n    def _get_height(self):\n        gc = PlotGraphicsContext((100, 100), dpi=72)\n        gc.set_font(self.label_font)\n        (w, h, descent, leading) = gc.get_full_text_extent(self.label)\n        return self._image.height() + h\n\n    @cached_property\n    def _get_bounds(self):\n        return [self.width, self.height]\n\n    def _draw_actual_button(self, gc):\n        x_offset = self.x + (self.width - self._image.width()) / 2\n        gc.draw_image(\n            self._image,\n            (x_offset, self.y + 2, self._image.width(), self._image.height()),\n        )\n\n        if self.label is not None and len(self.label) > 0:\n            gc.set_font(self.label_font)\n\n            (w, h, descent, leading) = gc.get_full_text_extent(self.label)\n            if w < self.width:\n                x_offset = self.x + (self.width - w) / 2\n            else:\n                x_offset = self.x\n\n            gc.set_text_position(x_offset, self.y - 8)\n            gc.show_text(self.label)\n\n\nclass IndexAxisLogButton(ToolbarButton):\n    label = \"X Log Scale\"\n    tooltip = \"Change index axis scale\"\n    image = \"zoom-fit-width\"\n\n    def perform(self, event):\n        if self.container.component.index_scale == \"linear\":\n            self.container.component.index_scale = \"log\"\n        else:\n            self.container.component.index_scale = \"linear\"\n        self.container.request_redraw()\n\n\nclass ValueAxisLogButton(ToolbarButton):\n    label = \"Y Log Scale\"\n    tooltip = \"Change value axis scale\"\n    image = \"zoom-fit-height\"\n\n    def perform(self, event):\n        if self.container.component.value_scale == \"linear\":\n            self.container.component.value_scale = \"log\"\n        else:\n            self.container.component.value_scale = \"linear\"\n        self.container.request_redraw()\n\n\nclass ZoomResetButton(ToolbarButton):\n    label = \"Zoom Reset\"\n    tooltip = \"Zoom Reset\"\n    image = \"zoom-original\"\n\n    def perform(self, event):\n        plot_component = self.container.component\n\n        for overlay in plot_component.overlays:\n            if isinstance(overlay, ZoomTool):\n                overlay._reset_state_pressed()\n\n        self.container.request_redraw()\n\n\nclass SaveAsButton(ToolbarButton):\n    label = \"Save As\"\n    tooltip = \"Save As\"\n    image = \"document-save\"\n\n    def perform(self, event):\n\n        plot_component = self.container.component\n\n        filter = \"PNG file (*.png)|*.png|\\nTIFF file (*.tiff)|*.tiff|\"\n        dialog = FileDialog(action=\"save as\", wildcard=filter)\n\n        if dialog.open() != OK:\n            return\n\n        # Remove the toolbar before saving the plot, so the output doesn't\n        # include the toolbar.\n        plot_component.remove_toolbar()\n\n        filename = dialog.path\n\n        width, height = plot_component.outer_bounds\n\n        gc = PlotGraphicsContext((width, height), dpi=72)\n        gc.render_component(plot_component)\n        try:\n            gc.save(filename)\n        except KeyError as e:\n            errmsg = (\n                \"The filename must have an extension that matches \"\n                \"a graphics format, such as '.png' or '.tiff'.\"\n            )\n            if str(e.message) != \"\":\n                errmsg = (\n                    \"Unknown filename extension: '%s'\\n\" % str(e.message)\n                ) + errmsg\n\n            error(None, errmsg, title=\"Invalid Filename Extension\")\n\n        # Restore the toolbar.\n        plot_component.add_toolbar()\n\n\nclass CopyToClipboardButton(ToolbarButton):\n    label = \"Copy Image\"\n    tooltip = \"Copy to the clipboard\"\n    image = \"edit-copy\"\n\n    def perform(self, event):\n        plot_component = self.container.component\n\n        # Remove the toolbar before saving the plot, so the output doesn't\n        # include the toolbar.\n        plot_component.remove_toolbar()\n\n        width, height = plot_component.outer_bounds\n\n        gc = PlotGraphicsContext((width, height), dpi=72)\n        gc.render_component(plot_component)\n\n        if ETSConfig.toolkit == \"wx\":\n            self._perform_wx(width, height, gc)\n        else:\n            pass\n\n        # Restore the toolbar.\n        plot_component.add_toolbar()\n\n    def _perform_wx(self, width, height, gc):\n        import wx\n\n        bitmap = wx.Bitmap.FromBufferRGBA(\n            width + 1, height + 1, gc.bmp_array.flatten()\n        )\n        data = wx.BitmapDataObject()\n        data.SetBitmap(bitmap)\n        if wx.TheClipboard.Open():\n            wx.TheClipboard.SetData(data)\n            wx.TheClipboard.Close()\n        else:\n            wx.MessageBox(\"Unable to open the clipboard.\", \"Error\")\n\n\nclass ExportDataToClipboardButton(ToolbarButton):\n    label = \"Copy Data\"\n    tooltip = \"Copy data to the clipboard\"\n    image = \"application-vnd-ms-excel\"\n\n    orientation = Enum(\"v\", \"h\")\n\n    def perform(self, event):\n        if ETSConfig.toolkit == \"wx\":\n            self._perform_wx()\n        elif ETSConfig.toolkit == \"qt4\":\n            self._perform_qt()\n        else:\n            pass\n\n    def _get_data_from_plots(self):\n        values = []\n        indices = []\n        for renderers in self.container.component.plots.values():\n            for renderer in renderers:\n                indices.append(renderer.index.get_data())\n                values.append(renderer.value.get_data())\n        return indices, values\n\n    def _serialize_data(self, indices, values):\n\n        # if all of rows are the same length, use faster algorithms,\n        # otherwise go element by element adding the necessary empty strings\n        if len(set([len(l) for l in values])) == 1:\n            data = [indices[0]] + values\n            if self.orientation == \"v\":\n                data = numpy.array(data).T.tolist()\n\n            data_str = \"\"\n            for row in data:\n                data_str += \",\".join([\"%f\" % v for v in row]) + \"\\n\"\n            return data_str\n\n        else:\n            # There might not be a single solution which fits all cases,\n            # so this is left to specific implementations to override\n            raise NotImplementedError()\n\n    def _perform_wx(self):\n        import wx\n\n        indices, values = self._get_data_from_plots()\n        data_str = self._serialize_data(indices, values)\n        data_obj = wx.TextDataObject(data_str)\n\n        if wx.TheClipboard.Open():\n            wx.TheClipboard.SetData(data_obj)\n            wx.TheClipboard.Close()\n        else:\n            wx.MessageBox(\"Unable to open the clipboard.\", \"Error\")\n\n    def _perform_qt(self):\n        from pyface.qt import QtGui\n\n        indices, values = self._get_data_from_plots()\n        data_str = self._serialize_data(indices, values)\n\n        QtGui.QApplication.clipboard().setText(data_str)\n", "path": "chaco/tools/toolbars/toolbar_buttons.py"}]}