1 /*
2  * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3  *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4  *
5  * This file is part of lsp-plugins
6  * Created on: 31 июл. 2017 г.
7  *
8  * lsp-plugins is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * any later version.
12  *
13  * lsp-plugins is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <ui/tk/tk.h>
23 
24 namespace lsp
25 {
26     namespace tk
27     {
28         //-----------------------------------------------------------------------------
29         // LSPListItem implementation
30 
LSPListItem(LSPItemList * list)31         LSPItemList::LSPListItem::LSPListItem(LSPItemList *list):
32             LSPItem()
33         {
34             pList       = list;
35         }
36 
LSPListItem(LSPItemList * list,const LSPItem * item)37         LSPItemList::LSPListItem::LSPListItem(LSPItemList *list, const LSPItem *item):
38             LSPItem(item)
39         {
40             pList       = list;
41         }
42 
~LSPListItem()43         LSPItemList::LSPListItem::~LSPListItem()
44         {
45             pList       = NULL;
46         }
47 
on_change()48         void LSPItemList::LSPListItem::on_change()
49         {
50             if (pList != NULL)
51                 pList->on_item_change(this);
52         }
53 
54         //-----------------------------------------------------------------------------
55         // LSPItemList implementation
56 
LSPItemList()57         LSPItemList::LSPItemList()
58         {
59         }
60 
~LSPItemList()61         LSPItemList::~LSPItemList()
62         {
63             drop_data();
64         }
65 
drop_data()66         void LSPItemList::drop_data()
67         {
68             size_t n            = vItems.size();
69             LSPListItem **ptr   = vItems.get_array();
70 
71             if (ptr != NULL)
72             {
73                 for (size_t i=0; i<n; ++i)
74                 {
75                     if (ptr != NULL)
76                         delete *ptr;
77                     ptr ++;
78                 }
79             }
80 
81             vItems.flush();
82         }
83 
create_item()84         LSPItemList::LSPListItem *LSPItemList::create_item()
85         {
86             return new LSPListItem(this);
87         }
88 
create_item(const LSPItem * item)89         LSPItemList::LSPListItem *LSPItemList::create_item(const LSPItem *item)
90         {
91             return new LSPListItem(this, item);
92         }
93 
on_item_change(LSPListItem * item)94         void LSPItemList::on_item_change(LSPListItem *item)
95         {
96         }
97 
on_item_add(size_t index)98         void LSPItemList::on_item_add(size_t index)
99         {
100         }
101 
on_item_remove(size_t index)102         void LSPItemList::on_item_remove(size_t index)
103         {
104         }
105 
on_item_swap(size_t idx1,size_t idx2)106         void LSPItemList::on_item_swap(size_t idx1, size_t idx2)
107         {
108         }
109 
on_item_clear()110         void LSPItemList::on_item_clear()
111         {
112         }
113 
clear()114         void LSPItemList::clear()
115         {
116             drop_data();
117             on_item_clear();
118         }
119 
add(const LSPItem * src)120         status_t LSPItemList::add(const LSPItem *src)
121         {
122             LSPListItem *item   = create_item(src);
123             if (item == NULL)
124                 return STATUS_NO_MEM;
125 
126             size_t index = vItems.size();
127             if (!vItems.add(item))
128             {
129                 delete item;
130                 return STATUS_NO_MEM;
131             }
132 
133             on_item_add(index);
134 
135             return STATUS_OK;
136         }
137 
add(LSPItem ** dst)138         status_t LSPItemList::add(LSPItem **dst)
139         {
140             LSPListItem *item   = create_item();
141             if (item == NULL)
142                 return STATUS_NO_MEM;
143 
144             size_t index = vItems.size();
145             if (!vItems.add(item))
146             {
147                 delete item;
148                 return STATUS_NO_MEM;
149             }
150 
151             on_item_add(index);
152             if (dst != NULL)
153                 *dst = item;
154 
155             return STATUS_OK;
156         }
157 
insert(ssize_t idx,const LSPItem * src)158         status_t LSPItemList::insert(ssize_t idx, const LSPItem *src)
159         {
160             if (idx > ssize_t(vItems.size()))
161                 return STATUS_INVALID_VALUE;
162 
163             LSPListItem *item   = create_item(src);
164             if (item == NULL)
165                 return STATUS_NO_MEM;
166 
167             if (!vItems.insert(item, idx))
168             {
169                 delete item;
170                 return STATUS_NO_MEM;
171             }
172 
173             on_item_add(idx);
174             return STATUS_OK;
175         }
176 
insert(ssize_t idx,LSPItem ** dst)177         status_t LSPItemList::insert(ssize_t idx, LSPItem **dst)
178         {
179             if (idx > ssize_t(vItems.size()))
180                 return STATUS_INVALID_VALUE;
181 
182             LSPListItem *item   = create_item();
183             if (item == NULL)
184                 return STATUS_NO_MEM;
185 
186             if (!vItems.insert(item, idx))
187             {
188                 delete item;
189                 return STATUS_NO_MEM;
190             }
191 
192             on_item_add(idx);
193             if (dst != NULL)
194                 *dst = item;
195             return STATUS_OK;
196         }
197 
remove(ssize_t idx,LSPItem * dst)198         status_t LSPItemList::remove(ssize_t idx, LSPItem *dst)
199         {
200             LSPListItem *item = vItems.get(idx);
201             if (item == NULL)
202                 return STATUS_INVALID_VALUE;
203             else if (!vItems.remove(idx))
204                 return STATUS_BAD_ARGUMENTS;
205 
206             on_item_remove(idx);
207 
208             status_t res = (dst != NULL) ? dst->set(item) : STATUS_OK;
209             delete item;
210 
211             return res;
212         }
213 
truncate(size_t size)214         status_t LSPItemList::truncate(size_t size)
215         {
216             for (size_t n = vItems.size(); n > size; --n)
217             {
218                 LSPListItem *item = vItems.get(n-1);
219                 if (!vItems.remove(n-1))
220                     return STATUS_BAD_STATE;
221 
222                 if (item != NULL)
223                     delete item;
224 
225                 on_item_remove(n);
226             }
227 
228             return STATUS_OK;
229         }
230 
swap(ssize_t idx1,ssize_t idx2)231         status_t LSPItemList::swap(ssize_t idx1, ssize_t idx2)
232         {
233             if (!vItems.swap(idx1, idx2))
234                 return STATUS_BAD_ARGUMENTS;
235 
236             if (idx1 != idx2)
237                 on_item_swap(idx1, idx2);
238             return STATUS_OK;
239         }
240 
get(ssize_t idx)241         LSPItem *LSPItemList::get(ssize_t idx)
242         {
243             return vItems.get(idx);
244         }
245 
set(ssize_t idx,const LSPItem * item)246         status_t LSPItemList::set(ssize_t idx, const LSPItem *item)
247         {
248             LSPListItem *dst    = vItems.get(idx);
249             if (dst == NULL)
250                 return STATUS_BAD_ARGUMENTS;
251 
252             return dst->set(item);
253         }
254 
index_of(const LSPItem * item) const255         ssize_t LSPItemList::index_of(const LSPItem *item) const
256         {
257             if (item == NULL)
258                 return STATUS_BAD_ARGUMENTS;
259 
260             cvector<LSPListItem> *st = const_cast<cvector<LSPListItem> *>(&vItems);
261             size_t n = st->size();
262             LSPListItem **arr = st->get_array();
263 
264             for (size_t i=0; i<n; ++i, ++arr)
265             {
266                 if (*arr == item)
267                     return i;
268             }
269 
270             return -1;
271         }
272 
273     } /* namespace tk */
274 } /* namespace lsp */
275